在 JavaScript 比较中应该使用哪个等于运算符 (== vs ===)?

IT技术 javascript operators equality equality-operator identity-operator
2020-12-14 21:44:35

我正在使用JSLint来检查 JavaScript,并且在执行诸如语句内部进行比较类的操作时,它会返回许多建议以将==(两个等号)替换===(三个等号)idSele_UNVEHtype.value.length == 0if

有没有性能优势,以代替=====

由于存在许多比较运算符,因此任何性能改进都会受到欢迎。

如果不发生类型转换,性能会不会比==?

6个回答

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

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

==运营商将比较平等做任何必要的类型转换之后===运营商将不会进行转换,因此,如果两个值是不一样的类型===将简单地返回false两者都一样快。

引用 Douglas Crockford 出色的JavaScript: The Good Parts

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

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

平等比较表

缺乏传递性令人担忧。我的建议是永远不要使用邪恶的双胞胎。相反,请始终使用===!==刚刚显示的所有比较都false===操作员进行了比较


更新:

@Casebash在评论和@Phillipe Laybaert 关于对象回答中提出了一个好观点对于对象,=====彼此一致地行动(除非在特殊情况下)。

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

特殊情况是当您将一个基元与一个评估为相同基元的对象进行比较时,由于其toStringvalueOf方法。例如,考虑将字符串原语与使用String构造函数创建的字符串对象进行比较

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

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

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

为什么你需要使用-0
2021-02-11 21:44:35
软打字是一项功能显然 Crockford 指出了设计决策的一些“人工制品”,但软打字仍然是一个特性。如果使用得当,使用起来绝对没问题不要把婴儿和洗澡水一起扔掉。
2021-02-12 21:44:35
我还要指出 0 === -0 和 NaN !== NaN,这有时会令人困惑。如果您想区分 ±0 并考虑 NaN 相等,请使用 Object.is (ES2015)
2021-02-14 21:44:35
我有很多工作
2021-02-27 21:44:35

使用==运算符 ( Equality )

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

使用===运算符 ( Identity )

true === 1; //false
"2" === 2;  //false

这是因为相等运算符==确实输入了强制类型,这意味着解释器会在比较之前隐式地尝试转换值。

另一方面,身份运算符===不执行类型强制,因此在比较时不转换值,因此跳过一个步骤会更快(根据This JS benchmark test)。

这是==之间的相等比较的有趣可视化===

来源:https : //github.com/dorey/JavaScript-Equality-Table演示统一演示


var1 === var2

当使用===JavaScript的平等的测试,一切都是原样。
在评估之前没有任何东西被转换。

JS 中 === 的相等性评估

var1 == var2

==用于 JavaScript 相等性测试时,会发生一些奇怪的转换

JS 中 == 的相等性评估

Javascript 中的相等性总结

Javascript 中的平等


结论:

除非你完全了解了时髦的转换所发生的与==始终使用===

至少 == 比较是可交换的(即 (a==b) === (b==a))XD
2021-02-07 21:44:35
2021-02-22 21:44:35

在这里的答案中,我没有读到任何关于平等意味着什么的内容有人会说这===意味着相等和相同类型,但事实并非如此。它实际上意味着两个操作数都引用同一个 object,或者在值类型的情况下,具有相同的 value

因此,让我们使用以下代码:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

和这里一样:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

甚至:

var a = { };
var b = { };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

这种行为并不总是很明显。这个故事不仅仅是平等和同一类型。

规则是:

对于值类型(数字):
a === b如果ab具有相同的值并且属于相同类型,则返回 true

对于引用类型:
a === b如果ab引用完全相同的对象,则返回 true

对于字符串:
a === b如果ab都是字符串并且包含完全相同的字符返回 true


字符串:特殊情况...

字符串不是值类型,但在 Javascript 中它们的行为类似于值类型,因此当字符串中的字符相同且长度相同时,它们将“相等”(如第三条规则所述)

现在变得有趣了:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types

但是这个怎么样?:

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

我认为字符串的行为类似于值类型?嗯,这取决于你问谁......在这种情况下,a 和 b 不是同一类型。a是 类型Object,而b是 类型string请记住,使用String构造函数创建字符串对象会创建大多数情况下Object表现为字符串的类型

让我补充一下这个忠告:

如有疑问,请阅读规范

ECMA-262 是一种脚本语言的规范,JavaScript 是其方言。当然,在实践中,最重要的浏览器的行为方式比对某些事情应该如何处理的深奥定义更重要。但是理解为什么new String("a") !== "a"是有帮助的

请让我解释如何阅读规范以澄清这个问题。我看到在这个非常古老的话题中,没有人对非常奇怪的效果有答案。所以,如果你能阅读规范,这将对你的职业有很大帮助。这是一种后天的技能。所以,让我们继续。

在 PDF 文件中搜索 === 将我带到规范的第 56 页:11.9.4。严格等于运算符 ( === ),在仔细阅读规范后,我发现:

11.9.6 严格相等比较算法
比较 x === y,其中 x 和 y 是值,产生truefalse这样的比较如下执行:
  1. 如果 Type(x) 与 Type(y) 不同,则返回false
  2. 如果 Type(x) 为 Undefined,则返回true
  3. 如果 Type(x) 为 Null,则返回true
  4. 如果 Type(x) 不是 Number,则转到步骤 11。
  5. 如果 x 是NaN,则返回false
  6. 如果 y 是NaN,则返回false
  7. 如果 x 与 y 的数值相同,则返回true
  8. 如果 x 是 +0 并且 y 是 -0,则返回true
  9. 如果 x 是 -0 并且 y 是 +0,则返回true
  10. 返回false
  11.如果Type(x)是String,那么如果x和y是完全相同的字符序列(长度相同,对应位置的字符相同),则返回true否则,返回false
  12. 如果 Type(x) 是布尔值,如果 x 和 y 都为或都为,则返回否则,返回false   13.返回
如果 x 和 y 指的是同一个对象,或者如果它们指的是相互连接的对象(见 13.1.2)。否则,返回false

有趣的是第 11 步。是的,字符串被视为值类型。但这并不能解释为什么new String("a") !== "a"我们是否有不符合 ECMA-262 的浏览器?

没那么快!

让我们检查操作数的类型。将它们包装在typeof() 中,亲自尝试一下我发现new String("a")是一个对象,并且使用了第 1 步:如果类型不同,则返回false

如果您想知道为什么new String("a")不返回字符串,那么来做一些阅读规范的练习怎么样?玩得开心!


Aidiakapi 在下面的评论中写道:

从规范

11.2.2 新运营商

如果 Type(constructor) 不是 Object,则抛出 TypeError 异常。

换句话说,如果 String 不是 Object 类型,它就不能与 new 运算符一起使用。

new总是返回一个对象,即使对于String构造函数也是如此。唉!字符串的值语义(参见步骤 11)丢失了。

这最终意味着:new String("a") !== "a"