我们从数学中了解到许多比较运算符。
在 JavaScript 中,它们这样写
- 大于/小于:
a > b
、a < b
。 - 大于/小于或等于:
a >= b
、a <= b
。 - 等于:
a == b
,请注意双等号==
表示相等测试,而单个等号a = b
表示赋值。 - 不等于:在数学中,符号是
≠
,但在 JavaScript 中,它写成a != b
。
在本文中,我们将详细了解不同类型的比较以及 JavaScript 如何进行比较,包括一些重要的特性。
在本文的最后,您将找到一个避免与“JavaScript 怪癖”相关的问题的良方。
布尔值是结果
所有比较运算符都返回布尔值
true
- 表示“是”、“正确”或“真”。false
- 表示“否”、“错误”或“假”。
例如
alert( 2 > 1 ); // true (correct)
alert( 2 == 1 ); // false (wrong)
alert( 2 != 1 ); // true (correct)
比较结果可以分配给变量,就像任何值一样
let result = 5 > 4; // assign the result of the comparison
alert( result ); // true
字符串比较
为了查看一个字符串是否大于另一个字符串,JavaScript 使用所谓的“字典”或“词典”顺序。
换句话说,字符串是逐个字母进行比较的。
例如
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
比较两个字符串的算法很简单
- 比较两个字符串的第一个字符。
- 如果第一个字符串的第一个字符大于(或小于)另一个字符串的第一个字符,那么第一个字符串就大于(或小于)第二个字符串。我们完成了。
- 否则,如果两个字符串的第一个字符相同,则以相同的方式比较第二个字符。
- 重复此步骤,直到任一字符串结束。
- 如果两个字符串的长度相同,则它们相等。否则,较长的字符串更大。
在上面的第一个示例中,比较 'Z' > 'A'
在第一步就得到了结果。
第二个比较 'Glow'
和 'Glee'
需要更多步骤,因为字符串是逐个字符进行比较的
G
与G
相同。l
与l
相同。o
大于e
。在此处停止。第一个字符串更大。
上面给出的比较算法与字典或电话簿中使用的算法大致相同,但并不完全相同。
例如,大小写很重要。大写字母 "A"
不等于小写字母 "a"
。哪一个更大?小写字母 "a"
。为什么?因为小写字符在 JavaScript 使用的内部编码表(Unicode)中具有更大的索引。我们将在 字符串 一章中详细了解此内容的具体细节和后果。
不同类型的比较
在比较不同类型的变量时,JavaScript 会将变量转换为数字。
例如
alert( '2' > 1 ); // true, string '2' becomes a number 2
alert( '01' == 1 ); // true, string '01' becomes a number 1
对于布尔值,true
变成 1
,false
变成 0
。
例如
alert( true == 1 ); // true
alert( false == 0 ); // true
有可能在同一时间
- 两个值相等。
- 其中一个作为布尔值是
true
,另一个作为布尔值是false
。
例如
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
从 JavaScript 的角度来看,这个结果很正常。相等性检查使用数字转换转换值(因此 "0"
变为 0
),而显式的 Boolean
转换使用另一组规则。
严格相等性
常规相等性检查 ==
有一个问题。它不能区分 0
和 false
alert( 0 == false ); // true
空字符串也会发生同样的事情
alert( '' == false ); // true
这是因为不同类型的操作数会被相等性运算符 ==
转换为数字。空字符串与 false
一样,变为零。
如果我们想区分 0
和 false
该怎么办?
严格相等性运算符 ===
在不进行类型转换的情况下检查相等性。
换句话说,如果 a
和 b
是不同类型的,那么 a === b
会立即返回 false
,而不会尝试转换它们。
我们来试试
alert( 0 === false ); // false, because the types are different
还有一个“严格不等于”运算符 !==
,类似于 !=
。
严格相等性运算符写起来有点长,但它让事情变得显而易见,并且减少了出错的空间。
与 null 和 undefined 的比较
当 null
或 undefined
与其他值进行比较时,会出现一种非直观的行为。
- 对于严格相等性检查
===
-
这些值是不同的,因为它们各自是不同的类型。
alert( null === undefined ); // false
- 对于非严格检查
==
-
有一个特殊规则。这两个值是一对“甜蜜的伴侣”:它们彼此相等(就
==
的意义而言),但与任何其他值都不相等。alert( null == undefined ); // true
- 对于数学和其他比较
< > <= >=
-
null/undefined
会转换为数字:null
变为0
,而undefined
变为NaN
。
现在让我们看看在应用这些规则时发生的一些有趣的事情。更重要的是,如何避免陷入它们的陷阱。
奇怪的结果:null 与 0
让我们比较一下 null
和一个零
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
从数学上来说,这是很奇怪的。最后的结果表明“null
大于或等于零”,所以在上面的比较中,它必须是 true
,但它们都是 false
。
原因是相等性检查 ==
和比较 > < >= <=
的工作方式不同。比较将 null
转换为数字,将其视为 0
。这就是为什么 (3) null >= 0
为真而 (1) null > 0
为假。
另一方面,undefined
和 null
的相等性检查 ==
被定义为在没有任何转换的情况下,它们相等并且不等于任何其他值。这就是为什么 (2) null == 0
为假。
不可比较的 undefined
不应该将值 undefined
与其他值进行比较
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
它为什么如此讨厌零?总是假!
我们得到这些结果是因为
- 比较
(1)
和(2)
返回false
,因为undefined
被转换为NaN
,而NaN
是一个特殊的数字值,它对所有比较都返回false
。 - 相等性检查
(3)
返回false
,因为undefined
仅等于null
、undefined
,而不等于任何其他值。
避免问题
我们为什么要讨论这些示例?我们应该一直记住这些特殊性吗?嗯,不一定。实际上,这些棘手的事情会随着时间的推移逐渐变得熟悉,但有一种可靠的方法可以避免出现问题
- 除了严格相等
===
之外,谨慎对待任何与undefined/null
的比较。 - 不要对可能为
null/undefined
的变量使用比较>= > < <=
,除非你真的确定自己在做什么。如果变量可以具有这些值,请单独检查它们。
总结
- 比较运算符返回一个布尔值。
- 字符串按“字典”顺序逐个字母进行比较。
- 当比较不同类型的值时,它们会被转换为数字(排除严格相等检查)。
- 值
null
和undefined
相等==
彼此,不等于任何其他值。 - 在对可能偶尔为
null/undefined
的变量使用>
或<
等比较时要小心。单独检查null/undefined
是一个好主意。
评论
<code>
标记,对于多行 - 将其包装在<pre>
标记中,对于 10 行以上 - 使用沙盒 (plnkr,jsbin,codepen…)