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

我使用JSLint 的经历 JavaScript 和它的返回许多建议更换== (双等号)与=== (三级等号)做这样的事情进行比较时idSele_UNVEHtype.value.length == 0内部的if声明。

==替换为===有性能优势吗?

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

如果没有进行类型转换,是否会获得==以上的性能提升?

答案

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

参考: 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

使用===运算符( Identity

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

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

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

=====之间的相等比较的有趣的图形表示。

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


var1 === var2

当使用===进行 JavaScript 相等性测试时,一切保持原样。在评估之前,没有任何转换。

JS中===的相等性评估


var1 == var2

当使用==进行 JavaScript 相等性测试时,会发生一些时髦的转换。

JS中==的相等性评估

故事的道德启示:

除非您完全了解==的转换,否则请使用===

在这里的答案中,我什么都没有读到什么相等的意思。有人会说===表示equal 且具有相同的类型 ,但这并不是真的。实际上, 意味着两个操作数都引用相同的对象 ,或者在值类型的情况下,它们具有相同的 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

这种现象并不总是很明显。故事不只是平等和同类型。

规则是:

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

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

对于字符串:
如果ab都是字符串并且包含完全相同的字符,则a === b返回 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 不是同一类型。 aObject类型,而bstring类型。只需记住,使用String构造函数创建字符串对象会创建Object类型的Object ,该Object 大多数情况下都表现为字符串。

让我补充一下这个建议:

如有疑问,请阅读规格

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

请让我解释如何阅读规范以阐明此问题。我看到,在这个非常老的话题中,没有人对非常奇怪的结果有任何答案。因此,如果您可以阅读规范,这将对您的职业产生极大的帮助。这是一项后天的技能。因此,让我们继续。

在 PDF 文件中搜索 === 使我进入规范的第 56 页: 11.9.4。 Strict Equals 运算符(===) ,在仔细研究了规范性语言后,我发现:

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;否则,返回true 。否则,返回false
12. 如果 Type(x)为布尔值,则如果 x 和 y 均为true或均为false ,则返回true ;否则,返回false
13. 如果 x 和 y 指的是同一个对象,或者它们指的是彼此连接的对象,则返回true (请参见 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 运算符一起使用。

即使对于String构造函数, new也会始终返回 Object。 a!字符串的值语义(请参见步骤 11)丢失。

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

在 PHP 和 JavaScript 中,它是严格的相等运算符。这意味着它将比较类型和值。

我使用以下代码在 Firefox 中使用Firebug测试了此代码:

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");

我的结果(每次测试五次,取平均值):

==: 115.2
===: 114.4

因此,我想说微不足道的差别(可以记住超过 100000 次迭代)可以忽略不计。性能不是要做===的理由。键入安全性(就像在 JavaScript 中一样安全),代码质量也是如此。

在 JavaScript 中,它表示相同的值和类型。

例如,

4 == "4" // will return true

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

===运算符称为严格比较运算符,它确实==运算符不同。

让我们取 2 个变量 a 和 b。

为了使“a == b”评估为真,a 和 b 必须为相同的值

“a === b”的情况下,a 和 b 必须具有相同的值相同的类型 ,才能将其评估为 true。

请看下面的例子

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%的使用情况下,使用哪一个无关紧要,但是,有一天在您遇到某些意外行为时,很容易知道它们之间的区别。

它检查相同边的类型是否相等。

例:

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

另一个常见的例子:

null == undefined // returns "true", but in most cases a distinction is necessary