2021 年 10 月 1 日

比较

我们从数学中了解到许多比较运算符。

在 JavaScript 中,它们这样写

  • 大于/小于:a > ba < b
  • 大于/小于或等于:a >= ba <= 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

比较两个字符串的算法很简单

  1. 比较两个字符串的第一个字符。
  2. 如果第一个字符串的第一个字符大于(或小于)另一个字符串的第一个字符,那么第一个字符串就大于(或小于)第二个字符串。我们完成了。
  3. 否则,如果两个字符串的第一个字符相同,则以相同的方式比较第二个字符。
  4. 重复此步骤,直到任一字符串结束。
  5. 如果两个字符串的长度相同,则它们相等。否则,较长的字符串更大。

在上面的第一个示例中,比较 'Z' > 'A' 在第一步就得到了结果。

第二个比较 'Glow''Glee' 需要更多步骤,因为字符串是逐个字符进行比较的

  1. GG 相同。
  2. ll 相同。
  3. o 大于 e。在此处停止。第一个字符串更大。
不是真正的字典,而是 Unicode 顺序

上面给出的比较算法与字典或电话簿中使用的算法大致相同,但并不完全相同。

例如,大小写很重要。大写字母 "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 变成 1false 变成 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 转换使用另一组规则。

严格相等性

常规相等性检查 == 有一个问题。它不能区分 0false

alert( 0 == false ); // true

空字符串也会发生同样的事情

alert( '' == false ); // true

这是因为不同类型的操作数会被相等性运算符 == 转换为数字。空字符串与 false 一样,变为零。

如果我们想区分 0false 该怎么办?

严格相等性运算符 === 在不进行类型转换的情况下检查相等性。

换句话说,如果 ab 是不同类型的,那么 a === b 会立即返回 false,而不会尝试转换它们。

我们来试试

alert( 0 === false ); // false, because the types are different

还有一个“严格不等于”运算符 !==,类似于 !=

严格相等性运算符写起来有点长,但它让事情变得显而易见,并且减少了出错的空间。

与 null 和 undefined 的比较

nullundefined 与其他值进行比较时,会出现一种非直观的行为。

对于严格相等性检查 ===

这些值是不同的,因为它们各自是不同的类型。

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 为假。

另一方面,undefinednull 的相等性检查 == 被定义为在没有任何转换的情况下,它们相等并且不等于任何其他值。这就是为什么 (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 仅等于 nullundefined,而不等于任何其他值。

避免问题

我们为什么要讨论这些示例?我们应该一直记住这些特殊性吗?嗯,不一定。实际上,这些棘手的事情会随着时间的推移逐渐变得熟悉,但有一种可靠的方法可以避免出现问题

  • 除了严格相等 === 之外,谨慎对待任何与 undefined/null 的比较。
  • 不要对可能为 null/undefined 的变量使用比较 >= > < <=,除非你真的确定自己在做什么。如果变量可以具有这些值,请单独检查它们。

总结

  • 比较运算符返回一个布尔值。
  • 字符串按“字典”顺序逐个字母进行比较。
  • 当比较不同类型的值时,它们会被转换为数字(排除严格相等检查)。
  • nullundefined 相等 == 彼此,不等于任何其他值。
  • 在对可能偶尔为 null/undefined 的变量使用 >< 等比较时要小心。单独检查 null/undefined 是一个好主意。

任务

重要性:5

这些表达式的结果是什么?

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

一些原因

  1. 显然是真。
  2. 字典比较,因此为假。"a" 小于 "p"
  3. 同样,字典比较,第一个字符 "2" 大于第一个字符 "1"
  4. nullundefined 仅相等。
  5. 严格相等是严格的。两边的不同类型导致假。
  6. 类似于 (4)null 仅等于 undefined
  7. 不同类型的严格相等。
教程地图

评论

在评论之前阅读此内容...
  • 如果您有改进建议 - 请 提交 GitHub 问题 或提交拉取请求,而不是评论。
  • 如果您无法理解文章中的某些内容 - 请详细说明。
  • 要插入几行代码,请使用 <code> 标记,对于多行 - 将其包装在 <pre> 标记中,对于 10 行以上 - 使用沙盒 (plnkrjsbincodepen…)