本文转载自 掘金 作者:技术漫谈
和其他操作符一样,比较操作符也会有返回值,返回值为布尔值(Boolean)。
alert( 2 > 1 ); // true(正确)
alert( 2 == 1 ); // false(错误)
alert( 2 != 1 ); // true(正确)
和其他类型的值一样,比较的结果可以被赋值给任意变量:
let result = 5 > 4; // 把比较的结果赋值给 result
alert( result ); // true
在比较字符串的大小时,JavaScript 会使用**“字典(dictionary)”或“词典(lexicographical)”**顺序进行判定。 换言之,字符串是按字符(母)逐个进行比较的。
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
非真正的字典顺序,而是Unicode编码顺序 在上面的算法中,比较大小的逻辑与字典或电话簿中的排序很像,但也不完全相同。 比如说,字符串比较对字母大小写是敏感的。大写的 "A" 并不等于小写的 "a"。哪一个更大呢?实际上小写的 "a" 更大。这是因为在 JavaScript 使用的内部编码表中(Unicode),小写字母的字符索引值更大。我们会在 info:string 这章讨论更多关于字符串的细节。
当对不同类型的值进行比较时,JavaScript 会首先将其转化为数字(number)再判定大小。
alert( '2' > 1 ); // true,字符串 '2' 会被转化为数字 2
alert( '01' == 1 ); // true,字符串 '01' 会被转化为数字 1
对于布尔类型值,true 会被转化为 1、false 转化为 0。
alert( true == 1 ); // true
alert( false == 0 ); // true
有时候,以下两种情况会同时发生:
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true
对于 JavaScript 而言,这种现象其实挺正常的。因为 JavaScript 会把待比较的值转化为数字后再做比较(因此 "0" 变成了 0)。若只是将一个变量转化为 Boolean 值,则会使用其他的类型转换规则。
普通的相等性检查 == 存在一个问题,它不能区分出 0 和 false:
alert( 0 == false ); // true
也同样无法区分空字符串和 false:
alert( '' == false ); // true
这是因为在比较不同类型的值时,处于相等判断符号 == 两侧的值会先被转化为数字。空字符串和 false 也是如此,转化后它们都为数字 0。如果我们需要区分 0 和 false,该怎么办?
换句话说,如果 a 和 b 属于不同的数据类型,那么 a === b 不会做任何的类型转换而立刻返回 false
alert( 0 === false ); // false,因为被比较值的数据类型不同
同样的,与“不相等”符号 != 类似,“严格不相等”表示为 !==。 严格相等的操作符虽然写起来稍微长一些,但是它能够很清楚地显示代码意图,降低你犯错的可能性。
当使用 null 或 undefined 与其他值进行比较时,其返回结果常常出乎你的意料。 当使用严格相等 === 比较二者时:它们不相等,因为它们属于不同的类型。
alert( null === undefined ); // false
当使用非严格相等 == 比较二者时:JavaScript 存在一个特殊的规则,会判定它们相等。他们俩就像“一对恋人”,仅仅等于对方而不等于其他任何的值(只在非严格相等下成立)。
alert( null == undefined ); // true
当使用数学式或其他比较方法 < > <= >= 时:null/undefined 会被转化为数字。null 被转化为 0,undefined 被转化为 NaN。 下面让我们看看,这些规则会带来什么有趣的现象。同时更重要的是,我们需要从中学会如何远离这些特性带来的“陷阱”。
通过比较 null 和 0 可得:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
是的,上面的结果完全打破了你对数学的认识。在最后一行代码显示“null 大于等于 0”的情况下,前两行代码中一定会有一个是正确的,然而事实表明它们的结果都是 false。 为什么会出现这种反常结果,这是因为相等性检测 == 和普通比较符 > < >= <= 的代码逻辑是相互独立的。进行值的比较时,null 会被转化为数字,因此它被转化为了 0。这就是为什么(3)中 null >= 0 返回值是 true,(1)中 null > 0 返回值是 false。 另一方面,undefined 和 null 在相等性检测 == 中不会进行任何的类型转换,它们有自己独立的比较规则,所以除了它们之间互等外,不会等于任何其他的值。这就解释了为什么(2)中 null == 0 会返回 false。
undefined 不应该被与其他值进行比较:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
为何它看起来如此厌恶 0?返回值都是 false!
原因如下:
(1) 和 (2) 都返回 false 是因为 undefined 在比较中被转换为了 NaN,而 NaN 是一个特殊的数值型值,它与任何值进行比较都会返回 false。
(3) 返回 false 是因为这是一个相等性检测,而 undefined 只与 null 相等,不会与其他值相等
我们为何要研究上述示例?我们需要时刻记得这些古怪的规则吗?不,其实不需要。虽然随着代码写得越来越多,我们对这些规则也都会烂熟于胸,但是我们需要更为可靠的方法来避免潜在的问题: 除了严格相等 === 外,其他凡是有 undefined/null 参与的比较,我们都需要额外小心。 除非你非常清楚自己在做什么,否则永远不要使用 >= > < <= 去比较一个可能为 null/undefined 的变量。对于取值可能是 null/undefined 的变量,请按需要分别检查它的取值情况。
先自己做题目再看答案。 以下表达式的执行结果是?
5 > 4
"apple" > "pineapple"
"2" > "12"
undefined == null
undefined === null
null == "\n0\n"
null === +"\n0\n"
5 > 4 → true
"apple" > "pineapple" → false
"2" > "12" → true
undefined == null → true
undefined === null → false
null == "\n0\n" → false
null === +"\n0\n" → false
评论