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

我正在使用JSLint来通过JavaScript,并且它返回了很多build议,以便在比较idSele_UNVEHtype.value.length == 0时候用=== (三个等号)replace== (两个等号) if声明。

===replace==是否有性能优势?

任何性能改进都会受到许多比较运算符的欢迎。

如果没有types转换发生,会有比==更好的性能吗?

标识( === )运算符的行为与相等( == )运算符的行为相同,除非不进行types转换,并且types必须相同才能被视为相等。

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

在进行任何必要的types转换之后==运算符将进行比较。 ===运算符不会执行转换,所以如果两个值不是相同的types===将简单地返回false 。 两者同样快捷。

引用Douglas Crockford的优秀JavaScript:好的部分 ,

JavaScript有两套相等运算符: ===!== ,以及他们的双胞胎==!= 。 好的那些以你期望的方式工作。 如果两个操作数具有相同的types并具有相同的值,则===产生true并且!==产生false 。 当操作数是相同的types时,双胞胎做正确的事情,但如果它们是不同的types,他们试图强制价值观。 他们所做的规则是复杂的,不可取的。 这些是一些有趣的情况:

 '' == '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 

传递性的缺乏是惊人的。 我的build议是永远不要使用邪恶的双胞胎。 相反,总是使用===!== 。 刚刚显示的所有比较都会使用===运算符产生false


更新:

@Casebash在评论和@Phillipe Laybaert对引用types的 回答中提出了一个很好的观点。 对于引用types=====一致地执行(除特殊情况外)。

 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 

特殊情况是,当你将一个文字与一个对象相比较时,由于它的toString或者valueOf方法,这个对象的计算结果是相同的。 例如,考虑将string文字与由String构造函数创build的string对象进行比较。

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

这里==运算符检查两个对象的值并返回true ,但是===看到它们不是相同的types并返回false 。 哪一个是正确的? 这真的取决于你想要比较的东西。 我的build议是完全绕过这个问题,只是不要使用String构造函数来创buildstring对象。

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

使用==运算符( 平等

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

使用===运算符( 标识

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

这是因为等号运算符==types强制 ,这意味着解释器在比较之前隐式地尝试转换值。

另一方面, 身份运算符===不会执行types强制 ,因此在比较时不会转换值。

在这里的答案中,我没有读到什么是平等的意思。 有人会说===意味着平等和相同的types ,但这不是真的。 它实际上意味着两个操作数都引用相同的对象 ,或者在值types的情况下具有相同的值

所以,我们来看下面的代码:

 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 

这种行为并不总是显而易见的。 这个故事比平等和相同的types更重要。

规则是:

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

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

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


string:特殊情况…

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

现在变得有趣了:

 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) 

我认为string行为像价值types? 那么,这取决于你问谁…在这种情况下,A和B是不同的types。 aObjecttypes,而bstringtypes。 只要记住使用String构造函数创build一个string对象就可以创build一些types为Object东西,这个东西在大多数情况下都是一个string。

=====之间的平等比较的有趣的graphics表示。

资料来源: http : //dorey.github.io/JavaScript-Equality-Table/

VAR1 === VAR2

当使用三个等号进行JavaScript相等性testing时,一切都是如此。 在评估之前没有任何东西会被转换

JS中对===的平等评估

VAR1 == VAR2

当使用两个等号进行JavaScript相等性testing时,会发生一些奇怪的转换。

JS中==的平等评估

道德故事:除非你完全理解两个平等的转换,否则使用三个等值。

我想补充一下这个build议:

如果有疑问,请阅读说明书 !

ECMA-262是JavaScript是一种方言的脚本语言的规范。 当然,在实践中,重要的浏览器如何performance比关于如何处理东西的深奥定义更重要。 但是理解为什么新的String(“a”)!==“a”是有帮助的。

请让我解释一下如何阅读规范来澄清这个问题。 我看到,在这个非常古老的话题中,没有人对这个奇怪的效果有一个回答。 所以,如果你可以阅读一个规范,这将有助于你的专业巨大。 这是一个获得的技能。 所以,让我们继续。

search===的PDF文件将我带到规范的第56页: 11.9.4。 严格的等号运算符(===) ,在涉及规范之后,我发现:

11.9.6严格平等比较algorithm
比较x === y,其中x和y是值,产生truefalse 。 这样的比较如下进行:
1.如果Type(x)与Type(y)不同,则返回false
2.如果Type(x)是Undefined,则返回true
3.如果Type(x)是Null,则返回true
4.如果types(x)不是数字,请转到步骤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)是布尔型,则返回true,如果x和y都为或者都为 ; 否则,返回false
13.如果x和y引用同一个对象,或者如果它们引用了彼此连接的对象(见13.1.2),则返回true 。 否则,返回false

有趣的是第11步。是的,string被视为值types。 但是这并不能解释为什么新的String(“a”)!==“a” 。 我们有不符合ECMA-262的浏览器吗?

不是那么快!

我们来检查一下操作数的types。 通过将它们包装在typeof()中来为自己尝试一下。 我发现新的String(“a”)是一个对象,并使用步骤1:如果types不同,则返回false

如果你想知道为什么新的String(“a”)不返回一个string,那么读一个​​规范的一些练习怎么样? 玩的开心!


Aidiakapi在下面的评论中写道:

从规范

11.2.2新运营商

如果Type(构造函数)不是Object,则引发TypeErrorexception。

换句话说,如果String不是Objecttypes的,那么它就不能和new运算符一起使用。

new总是返回一个Object,即使对于String构造函数也是如此。 唉! string的值语义(请参阅步骤11)已丢失。

这最后意味着: 新的String(“a”)!==“a”

在PHP和JavaScript中,它是一个严格的平等运算符。 这意味着,它将比较types和值。

我用Firebug在Firefox中testing了这个代码,如下所示:

 console.time("testEquality"); var n = 0; while(true) { n++; if(n==100000) break; } console.timeEnd("testEquality"); 

 console.time("testTypeEquality"); var n = 0; while(true) { n++; if(n===100000) break; } console.timeEnd("testTypeEquality"); 

我的结果(testing五次,平均):

 ==: 115.2 ===: 114.4 

所以我会说,微乎其微(这是超过10万次迭代,记住)可以忽略不计。 性能不是===的理由。 input安全性(当然,就像你将要使用JavaScript一样安全),代码质量是。

在JavaScript中,它意味着相同的价值和types。

例如,

 4 == "4" // will return true 

 4 === "4" // will return false 

===运算符被称为严格比较运算符,它不同于==运算符。

让我们拿2个variablesa和b。

对于“a == b”来评估真正的a和b需要是相同的值

“a === b”的情况下,a和b必须是相同的值 ,也是相同的types才能评估为真。

以下面的例子

 var a = 1; var b = "1"; if (a == b) //evaluates to true as a and b are both 1 { alert("a == b"); } if (a === b) //evaluates to false as a is not the same type as b { alert("a === b"); } 

综上所述 , 使用==运算符可能评估为true,如果您不希望使用===运算符会更安全。

在90%的使用情况下,你使用哪一个并不重要,但是当你有一天出现一些意想不到的行为时,知道这个差异是很方便的。

它会检查相同的边是否相同的types以及价值

例:

 '1' === 1 // will return "false" because `string` is not a `number` 

常见示例:

 0 == '' // will be "true", but it's very common to want this check to be "false" 

JavaScript执行stream程图严格相等/比较'==='

Javascript严格平等

Javascript执行stream程图非严格相等/比较'=='

Javascript不平等

JavaScript === vs ==

 0==false // true 0===false // false, because they are of a different type 1=="1" // true, auto type coercion 1==="1" // false, because they are of a different type 

在典型的脚本中不会有性能差异。 更重要的可能是千“===”比千“==”重1 KB。JavaScript分析器可以告诉你在你的情况下是否存在性能差异。

但是我个人会做JSLintbuild议的。 这个build议不是因为性能问题,而是因为types强制手段('\t\r\n' == 0)是真的。

这意味着没有types强制types强制意味着平等意味着JavaScript不会自动将任何其他数据types转换为string数据types

 0==false // true,although they are different types 0===false // false,as they are different types 2=='2' //true,different types,one is string and another is integer but javaScript convert 2 to string by using == operator 2==='2' //false because by using === operator ,javaScript do not convert integer to string 2===2 //true because both have same value and same types 

相等的比较运算符==令人困惑,应该避免。

如果你必须忍受它,那么记住以下三件事:

  1. 这不是传递的: (a == b)(b == c)不会导致(a == c)
  2. 它的否定是相互排斥的: (a == b)(a!= b)总是保持相反的布尔值,所有a和b。
  3. 如有疑问,可以借鉴以下真相表:

在JAVASCRIPT中的等式算子真值表

  • 表中的每一行都是一组3个相互“相等”的值,这意味着其中的任何两个值都相等,使用等号== *

**奇怪:请注意,第一列的任何两个值在这个意义上是不相等的。**

 '' == 0 == false // Any two values among these 3 ones are equal with the == operator '0' == 0 == false // Also a set of 3 equal values, note that only 0 and false are repeated '\t' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- '\r' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- '\n' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- '\t\r\n' == 0 == false // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- null == undefined // These two "default" values are not-equal to any of the listed values above NaN // NaN is not equal to any thing, even to itself. 

在您的使用中,两个操作之间不会有任何性能差异。 没有types转换可以完成,因为两个参数都是相同的types。 两个操作都会进行types比较,然后进行值比较。

是! 这很重要。

=== javascript中的运算符检查值以及as ==运算符只检查值的types(如果需要,则进行types转换)

在这里输入图像描述

你可以很容易地testing它。 将以下代码粘贴到HTML文件中,并在浏览器中打开它

 <script> function onPageLoad() { var x = "5"; var y = 5; alert(x === 5); }; </script> </head> <body onload='onPageLoad();'> 

你会得到“ ”的警报。 现在修改onPageLoad()方法来alert(x == 5); 你会变得真实

为什么==是如此不可预测?

当你比较一个空string""与数字零0时,你会得到什么?

true

是的,这是正确的==一个空string和数字零是同一时间。

它并不止于此,还有另外一个:

 '0' == false // true 

事情变得非常奇怪与数组。

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

然后用string来回避

 [1,2,3] == '1,2,3' // true - REALLY?! '\r\n\t' == 0 // true - Come on! 

情况变得更糟:

什么时候不相等?

 let a = '' // empty string let b = 0 // zero let c = '0' // zero string a == b // true - ok... b == c // true - so far so good... a == c // **FALSE** - Plot twist! 

而这仅仅是你用原始的东西得到的疯狂的东西。

当对对象使用==时,这是一个全新的疯狂级别。

在这一点上你可能想知道…

为什么会发生?

那么这是因为不像“triple equals”( === ),它只是检查两个值是否相同。

==做了一大堆其他的东西

它具有特殊的函数处理,特殊处理空值,未定义,string,你的名字。

它变得非常古怪。

事实上,如果你试图写一个函数来做== ,它会看起来像这样:

 function isEqual(x, y) { // if `==` were a function if(typeof y === typeof x) return y === x; // treat null and undefined the same 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 either value is a string // convert the function into a string and compare 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; // convert x and y into numbers if they are not already use the "+" trick if(typeof x !== "number") x = +x; if(typeof y !== "number") y = +y; // actually the real `==` is even more complicated than this, especially in ES6 return x === y; } function toPrimitive(obj) { var value = obj.valueOf(); if(obj !== value) return value; return obj.toString(); } 

那么这是什么意思?

这意味着==是复杂的。

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

这意味着你最终可能会有错误。

所以这个故事的寓意是…

让你的生活更简单

使用===而不是==

结束。

这是一个严格的检查testing。

特别是如果你在0和false之间进行检查,并且为null,这是一件好事。

例如,如果您有:

 $a = 0; 

然后:

 $a==0; $a==NULL; $a==false; 

所有返回true,你可能不想要这个。 假设您有一个函数可以返回数组的第0个索引,或者在失败时返回false。 如果你检查“==”为false,你可能会得到一个令人困惑的结果。

因此,与上述相同的事情,但一个严格的testing:

 $a = 0; $a===0; // returns true $a===NULL; // returns false $a===false; // returns false 

一个简单的例子是

 2 == '2' -> true, values are SAME because of type conversion. 2 === '2' -> false, values are NOT SAME because of no type conversion. 

'==='运算符检查值以及variables的types是否相等。

'=='运算符只是检查variables的值是否相等。

JSLint有时会给你不切实际的理由去修改东西。 如果types已经相同, ===具有与==完全相同的性能。

只有当types不一样时才会更快,在这种情况下,它不会尝试转换types,而是直接返回false。

所以, 恕我直言, JSLint也许用来写新的代码,但无用的过度优化应该不惜一切代价避免。

意思是说,当你知道它只能是一个string的事实时,没有理由把== to ===改成== to === ,就像if (a == 'test')

以这种方式修改大量代码会浪费开发人员和审阅者的时间,而且什么也不做。

前两个答案都提到==意味着平等和===意味着身份。 不幸的是,这个说法是错误的。

如果==的两个操作数都是对象,则比较它们是否是同一个对象。 如果两个操作数指向相同的对象,那么相等的操作符返回true。 否则,两者是不相等的。

 var a = [1, 2, 3]; var b = [1, 2, 3]; console.log(a == b) // false console.log(a === b) // false 

在上面的代码中,==和===都是false,因为a和b不是同一个对象。

也就是说,如果==的两个操作数都是对象,则==与===的行为相同,这也意味着标识。 这两个操作符的本质区别在于types转换。 ==在转换之前有转换,但===不转换。

从核心JavaScript参考

===如果操作数严格相等(见上),则不返回types转换。

作为一个经验法则,我通常会使用===而不是== (和!==而不是!= )。

在上面的答案中解释了原因,Douglas Crockford也很清楚( JavaScript:The Good Parts )。

但是有一个例外== null是检查'是空还是未定义'的有效方法:

 if( value == null ){ // value is either null or undefined } 

例如,jQuery 1.9.1使用这个模式43次, eqnull 语法检查器甚至提供了eqnull放宽选项。

从jQuery风格指南 :

应该使用严格的等式检查(===)来支持==。 唯一的例外是检查未定义和空的空方式。

 // Check for both undefined and null values, for some important reason. undefOrNull == null; 

问题是,你可能很容易陷入麻烦,因为JavaScript有很多隐式转换意味着…

 var x = 0; var isTrue = x == null; var isFalse = x === null; 

这很快就会成为一个问题。 为什么隐式转换为“邪恶”的最好的例子可以采取从MFC / C + +这实际上将编译由于从CString隐式转换为HANDLE这是一个指针typedeftypes的代码…

 CString x; delete x; 

这在运行时显然是非常不明确的事情…

谷歌隐式转换在C + +和STL得到一些反对它的论据…

只是

== means comparison between operands with type conversion

=== means comparison between operands without type conversion

Equality comparison:

Operator ==

Returns true, when both operands are equal. The operands are converted to the same type before being compared.

 >>> 1 == 1 true >>> 1 == 2 false >>> 1 == '1' true 

Equality and type comparison:

Operator ===

Returns true if both operands are equal and of the same type. It's generally better and safer if you compare this way, because there's no behind-the-scenes type conversions.

 >>> 1 === '1' false >>> 1 === 1 true 

null and undefined are nothingness, that is,

 var a; var b = null; 

Here a and b do not have values. Whereas, 0, false and '' are all values. One thing common beween all these are that they are all falsy values, which means they all satisfy falsy conditions.

So, the 0, false and '' together form a sub-group. And on other hand, null & undefined form the second sub-group. Check the comparisons in the below image. null and undefined would equal. The other three would equal to each other. But, they all are treated as falsy conditions in JavaScript.

在这里输入图像说明

This is same as any object (like {}, arrays, etc.), non-empty string & Boolean true are all truthy conditions. But, they are all not equal.

* Operators === vs == *

 1 == true => true true == true => true 1 === true => false true === true => true