乐闻世界logo
搜索文章和话题

JS 中应该使用哪个等于运算符 == 和 === ?

5个答案

1
2
3
4
5

在 JavaScript 中应该使用哪个等于运算符(== 与 ===)来做比较操作?

在 JavaScript 的世界里,比较运算符是我们日常编码中不可或缺的一部分。它们帮助我们理解和判断不同变量或表达式的值是否相等。当我们提到相等比较时,有两个非常相似但又截然不同的运算符:==(相等运算符)和 ===(严格相等运算符)。了解它们的区别,对于写出可靠和高效的代码至关重要。

== 相等运算符:类型强制转换的魔术师

== 运算符在 JavaScript 中被称为“宽松相等”或者“非严格相等”。当使用 == 比较两个值时,如果它们不是同一类型,JavaScript 会尝试类型转换,将它们转换成相同的类型后再做比较。这种类型转换通常被称为“类型强制转换”。

举个栗子 🌰

javascript
0 == '0'; // true,因为字符串 '0' 被强制转换成了数字 0 '1' == 1; // true,同上 null == undefined; // true,null 和 undefined 在非严格相等的情况下被认为是相等的

== 运算符的这种行为可能会引起一些意想不到的结果,有时会导致难以发现的 bug。因此,它经常被认为是 JavaScript 中一种不那么可靠的比较方式。

=== 严格相等运算符:精确无误的严格管家

== 运算符不同,=== 运算符在比较时不会进行类型转换。如果两个值的类型不同,它们就被认为是不相等的。因此,=== 被称为“严格相等”运算符。

再举个栗子 🌰

javascript
0 === '0'; // false,因为它们类型不同:一个是数字,一个是字符串 '1' === 1; // false,同上 null === undefined; // false,null 和 undefined 类型不同

使用 === 运算符可以让你的代码逻辑更加清晰、可预测,并且减少隐藏 bug 的风险。

那么,我们应该怎么选择?

在大多数情况下,推荐使用 === 严格相等运算符,因为它提供了类型安全的比较,能减少许多不必要的问题。当你明确需要进行类型转换时,才考虑使用 ==

最佳实践

假设你在处理一个 web 表单,用户输入的是数字字符串,而你需要将其与数字类型的值进行比较。

javascript
const userInput = '123'; const targetValue = 123; // 使用 ==,因为我们明确知道两边的值应该是相同的,即使类型不同 if (userInput == targetValue) { console.log('用户输入匹配!'); }

在这种情况下,你可能会选择使用 ==,因为它简化了代码。然而,为了保持更好的代码质量和可维护性,你应该考虑显式地转换类型,然后使用 === 进行比较。

javascript
const userInput = '123'; const targetValue = 123; // 显式转换类型,然后使用 === 进行比较 if (Number(userInput) === targetValue) { console.log('用户输入匹配!');

2024年6月29日 12:07 回复

严格相等运算符 ( ===) 的行为与抽象相等运算符 ( ==) 相同,只是不进行类型转换,并且类型必须相同才能被视为相等。

参考:JavaScript 教程:比较运算符

_在进行任何必要的类型转换后,_该==运算符将比较是否相等。该运算符不会进行转换,因此如果两个值不同,类型将简单地返回。两者都同样快。===``===``false

引用 Douglas Crockford 的优秀JavaScript: The Good Parts

JavaScript 有两组相等运算符:===and !==,以及它们的邪恶双胞胎==and !=。好的产品会按照您期望的方式工作。如果两个操作数类型相同且值相同,则===生成true!==生成false。当操作数具有相同类型时,邪恶双胞胎会做正确的事情,但如果它们具有不同类型,它们会尝试强制这些值。他们这样做的规则既复杂又难以记住。以下是一些有趣的案例:

shell
'' == '0' // false 0 == '' // true 0 == '0' // true
shell
false == 'false' // false false == '0' // true
shell
false == undefined // false false == null // false null == undefined // true
shell
' \t\r\n ' == 0 // true

平等比较表

传递性的缺乏令人震惊。我的建议是永远不要使用邪恶的双胞胎。相反,请始终使用===!==。刚刚显示的所有比较都false===运算符有关。


更新

@Casebash在评论和@Phillipe Laybaert 关于对象的 回答中提出了一个很好的观点。对于对象来说,彼此的==行为===一致(特殊情况除外)。

shell
var a = [1,2,3]; var b = [1,2,3]; var c = { x: 1, y: 2 }; var d = { x: 1, y: 2 }; var e = "text"; var f = "te" + "xt"; a == b // false a === b // false c == d // false c === d // false e == f // true e === f // true

特殊情况是当您将一个基元与一个由于其toStringorvalueOf方法而计算结果相同的对象进行比较时。例如,考虑将字符串基元与使用String构造函数创建的字符串对象进行比较。

shell
"abc" == new String("abc") // true "abc" === new String("abc") // false

这里==操作符检查两个对象的值并返回true,但===发现它们的类型不同并返回false。哪一个是正确的?这实际上取决于您要比较的内容。我的建议是完全绕过这个问题,只是不要使用String构造函数从字符串文字创建字符串对象。

参考
https://262.ecma-international.org/5.1/#sec-11.9.3

2024年6月29日 12:07 回复

为什么 == 这么难以预测?

当你将空字符串 "" 与数字零 0 进行比较时,会得到什么结果?

true

没错,根据 == 的规则,一个空字符串和数字零被认为是相同的。

但这还不是全部。再看这个例子:

shell
'0' == false // true

数组的情况更加奇怪。

shell
[1] == true // true [] == false // true [[]] == false // true [0] == false // true

字符串的情况则更加怪异

shell
[1,2,3] == '1,2,3' // true - 真的吗?! '\r\n\t' == 0 // true - 这也太扯了吧!

情况还会变得更糟:

什么时候相等不等于相等?

shell
let A = '' // 空字符串 let B = 0 // 数字零 let C = '0' // 字符串中的零 A == B // true - 好吧... B == C // true - 到目前为止还不错... A == C // **FALSE** - 情节转折!

我们再来看一遍:

shell
(A == B) && (B == C) // true (A == C) // **FALSE**

这些疯狂的事情只发生在原始类型上。

当你使用 == 来比较对象时,情况会变得完全不同。

这时你可能会想...

为什么会这样发生?

这是因为不像 "三等号"(===)只检查两个值是否完全相同。

== 做了一大堆其他的事情

它对待函数、null、undefined、字符串等都有特殊处理。

事情变得相当混乱。

事实上,如果你尝试编写一个执行 == 相同操作的函数,它可能看起来像这样:

javascript
function isEqual(x, y) { // 如果 `==` 是一个函数 if (typeof y === typeof x) return y === x; // 将 null 和 undefined 视为相同 var xIsNothing = (y === undefined) || (y === null); var yIsNothing = (x === undefined) || (x === null); if (xIsNothing || yIsNothing) return (xIsNothing && yIsNothing); if (typeof y === "function" || typeof x === "function") { // 如果任一值是字符串 // 将函数转换为字符串并比较 if (typeof x === "string") { return x === y.toString(); } else if (typeof y === "string") { return x.toString() === y; } return false; } if (typeof x === "object") x = toPrimitive(x); if (typeof y === "object") y = toPrimitive(y); if (typeof y === typeof x) return y === x; // 如果 x 和 y 不是数字,则将它们转换为数字 if (typeof x !== "number") x = +x; if (typeof y !== "number") y = +y; // 实际上真正的 `==` 比这还要复杂,尤其是在ES6中 return x === y; } function toPrimitive(obj) { var value = obj.valueOf(); if (value !== obj) return value; return obj.toString(); }

这意味着什么?

意味着 == 很复杂。

因为它复杂,所以很难知道在使用它时会发生什么。

这意味着你可能会遇到bug。

故事的寓意是...

让你的生活变得简单些。

使用 === 而不是 ==

故事结束。

2024年6月29日 12:07 回复

在JavaScript中,nullundefined 都代表不存在的值,即:

javascript
var a; // a被声明了,但没有赋值,其值为undefined var b = null; // b被赋予了null,表示一个空值

这里变量 ab 都没有具体的值。相对地,0、false 和空字符串 '' 虽然代表各自的值,但它们有一个共同点:都被认为是假值(falsy value),也就是说,在条件判断中它们都会被当作 false

据此,0、false'' 可以看作是一组特殊的假值。而 nullundefined 则构成另一组特殊的无值。查看下面的比较图,nullundefined 在JavaScript中被认为是相等的。同理,0、false'' 也被认为彼此相等。尽管如此,它们在JavaScript中都符合假值的条件。

在此输入图像描述

与此相对,任何对象(如 {} 和数组等)、非空字符串以及布尔值 true 都被视为真值(truthy value),在条件判断中它们相当于 true。但是,这些真值并不意味着它们之间相等。

2024年6月29日 12:07 回复

在 JavaScript 中,你通常应该使用 === (严格等于) 运算符来进行比较操作,而不是 == (宽松等于) 运算符。

=== (严格等于) 运算符会比较两个值的类型和值,只有当两者都相等时,它才会返回 true。这意味着如果两个值的类型不同,它们永远不会被认为是严格相等的。

javascript
3 === '3' // false,因为一个是数字类型,另一个是字符串类型

== (宽松等于) 运算符会在比较之前将两个值进行类型转换(如果它们的类型不同的话),然后再比较它们的值。

javascript
3 == '3' // true,因为字符串 '3' 会被转换成数字 3

使用 === 可以避免由 JavaScript 自动类型转换导致的潜在错误和混淆,因此它通常是一个更好的选择。然而,必须指出在某些罕见情况下,如果你确实需要进行类型转换,那么使用 == 也是合适的。但在多数情况下,推荐使用 === 来确保代码的准确性和清晰性。

2024年6月29日 12:07 回复

你的答案