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

我使用JSLint来浏览JavaScript,并且在做比较语句内部的操作时,返回了很多建议来替换==(两个等号)===(三个等号)。idSele_UNVEHtype.value.length == 0if

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

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

如果没有类型转换发生,会不会有性能增益==

答案


除非没有完成类型转换,否则identity(===)运算符的行为与equality(==)运算符的行为相同,并且类型必须相同才能被视为相同。

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

在完成任何必要的类型转换之后==操作员将进行比较。该运营商将不会进行转换,因此,如果两个值是不一样的类型将简单地返回。两者同样快速。======false

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

JavaScript有两套平等运算符:===!==,他们的双胞胎==和孪生兄弟!=。好的那些以你期望的方式工作。如果两个操作数具有相同的类型并具有相同的值,则===生成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


使用==运算符(平等

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

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

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


在这里的答案中,我没有读过任何关于什么是平等的含义。有人会说这===意味着平等和相同的类型,但这不是真的。它实际上意味着两个操作数引用相同的对象,或者在值类型的情况下具有相同的值

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

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返回如果为truea,并b具有相同的价值,并且是同一类型的

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

对于字符串:
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是类型的Objectb而是类型的string。请记住,使用String构造函数创建一个字符串对象会创建一些类型Object,这些类型在大多数情况下表现为字符串。


之间的平等比较的一个有趣的图形表示=====

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

VAR1 === VAR2

当使用三个等号进行JavaScript相等性测试时,一切都是如此。评估前没有任何转化

VAR1 == VAR2

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

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


让我补充一下这个建议:

如有疑问,请阅读说明书

ECMA-262是一种脚本语言的规范,JavaScript是一种方言。当然在实践中,更重要的是浏览器的重要性如何,而不是对应该如何处理的深奥定义。但是理解为什么新的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,则返回true,如果x和y是完全相同的字符序列(相同长度和相同位置的相同字符); 否则,返回false
12.如果Type(x)是布尔值,则返回true,如果x和y都为或者都为 ; 否则,返回false
13.返回真实如果x和y指的是同一个对象,或者它们指向彼此连接的对象(见13.1.2)。否则,返回false

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

没那么快!

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

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


Aidiakapi在下面的评论中写道:

从规范

11.2.2新运营商

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

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

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

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

添加评论

友情链接:蝴蝶教程