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


我在用着 JSLint的 通过JavaScript,它返回了许多建议来替换 == (两个等于标志) === (三个等于标志)做比较时的事情 idSele_UNVEHtype.value.length == 0 里面的 if 声明。

替换是否有性能优势 == 同 ===

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

如果没有进行类型转换,那么是否会有性能提升 ==


5674
2017-12-11 14:19


起源


它可能对同一主题感兴趣 === vs ==,但在PHP中,可以在这里阅读: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/... - Marco Demaio
万一有人在2012年想知道: === 是 办法 比...快 ==。 jsperf.com/comparison-of-comparisons - Ry-♦
@minitech它应该是因为它不进行类型转换 - Umur Kontacı
@minitech,我怀疑任何人都会通过使用显着提高他们的应用程序 === 过度 ==。实际上,基准测试并没有在现代浏览器上显示出很大的差异。就个人而言,我通常使用 == 除非我真的需要严格的平等。 - this.lau_
@johndodo:过早优化只是一件事,因为从可维护性和可读性的角度来看,优化的代码可能不太理想,但是如果类型转换功能如此 == 不需要,使用 === 相反是良好的做法,而不是过早的优化。什么都没有 === 这会降低代码的可维护性或可读性。 - Robert Harvey♦


答案:


身份 (===)运算符的行为与相等相同(==运算符除了没有进行类型转换,并且类型必须相同才能被认为是相等的。

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

== 运营商将比较平等 完成任何必要的类型转换后。该 === 运营商会  进行转换,因此如果两个值不是同一类型 === 只会回来 false。两者都同样快。

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

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

特殊情况是将文字与评估相同文字的对象进行比较时,由于它的原因 toString 要么 valueOf 方法。例如,考虑将字符串文字与由字符串对象创建的字符串对象进行比较 String 构造函数。

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

在这里 == operator正在检查两个对象的值并返回 true,但是 === 看到他们不是同一类型并返回 false。哪一个是正确的?这真的取决于你想要比较的东西。我的建议是完全绕过这个问题,不要使用 String 构造函数来创建字符串对象。

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


5728
2017-12-11 14:25



如果类型相同,===不会更快。如果类型不相同,===会更快,因为它不会尝试进行转换。 - Bill the Lizard
===永远不会慢于==。它们都进行类型检查,所以===与==相比没有做任何额外的事情,但类型检查可能允许===在类型不同时更快退出。 - Bill the Lizard
用=== /!==替换所有== /!=会增加js文件的大小,然后需要更多的时间来加载。 :) - Marco Demaio
“......他们这样做的规则是复杂和不可取的......”现在这些陈述使你在编程时感到如此安全...... - Johan
有时JavaScript的类型系统让我想要逃避尖叫。 - Yawar


使用 ==操作员(平等

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

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

另一方面, 身份运营商 === 不做类型强制,因此在比较时不会转换值。


990
2018-06-05 19:11



@Software Monkey:不适用于值类型(数字,布尔值,...) - Philippe Leybaert
type coercion vs type casting vs type convertion: stackoverflow.com/questions/8857763/... - Adrien Be
由于没有人提到Javascript Equality Table,这里是: dorey.github.io/JavaScript-Equality-Table - blaze
在第一个语句中,您确定'true'转换为1而不是1转换为true吗? - Shadi Namrouti
“平等”和“身份”这两个术语来自哪里?该标准不使用这些条款。它叫 == “抽象平等”,它呼吁 === “严格平等”。授予召唤 == 任何形式的“平等”都是恕我直言,因为它不是传递性的,但为什么要狡辩?我对“身份”有更多的疑问;我觉得这个词很有误导性,尽管它“有效”。但严肃的是,谁创造了“身份”一词?我搜索标准,找不到它。 - Ray Toal


在这里的答案中,我没有读到任何关于什么的内容 等于 手段。有人会说 === 手段 相同和相同的类型,但那不是真的。它实际上意味着 两个操作数都引用同一个对象,或者如果是 值类型,具有相同的值

那么,我们来看下面的代码:

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 如果返回true a 和 b 具有相同的值并且具有相同的类型

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

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


字符串:特例......

字符串不是值类型,但在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 表现为字符串 大多数时候


546
2018-05-05 05:21



activa:我会澄清,字符串只有在它们是文字的时候才是相同的。 new String(“abc”)===“abc”是假的(根据我的研究)。 - Lawrence Dol
new Number() == "0"。在Firefox中: (function(){}) == "function () {\n}" - Thomas Eding
谢谢你解释原因 new String("123") !== "123"。它们是不同的类型。简单,但令人困惑。 - styfle
String 对象表现为字符串 任何其他对象。 new String 永远不应该使用,因为这不会创建真正的字符串。一个真正的字符串,可以使用字符串文字或调用 String 作为一个功能 无  new, 例如: String(0); //"0", Real string, not an object - Esailija
但在您详细说明的情况下,运算符“==”的行为完全相同。 - Yaron Levi


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

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


var1 === var2

使用时 === 对于JavaScript相等测试,一切都是这样的。在评估之前没有任何东西被转换。

Equality evaluation of === in JS


var1 == var2

使用时 == 对于JavaScript相等测试,一些   时髦的转换发生了。

Equality evaluation of == in JS

故事的道德启示: 

使用 === 除非你完全理解   与之发生的转换 ==


522
2017-11-28 18:18



@mfeineis你的意思是===或!==而不是==或!=。不想混淆新的程序员;) - katalin_2003
@ katalin_2003 oops,你是对的===和!==,d ** n错别字,thx - mfeineis
@vsync:哇,那些滥用JQuery的人也说同样的话。我从来不知道你有这么多共同点......
@vsync:如果你 真的不希望类型相等,你 应该 使用 三等于! - SNag
这个答案太有用!!! - skiabox


让我补充一下这个忠告:

如有疑问,请阅读 规范 

ECMA-262是脚本语言的规范,JavaScript是一种方言。当然,在实践中,最重要的浏览器的行为方式比关于如何处理某些内容的深奥定义更重要。但了解原因很有帮助 new String(“a”)!==“a”

请让我解释如何阅读说明书以澄清这个问题。我看到在这个非常古老的话题中,没有人能够得到非常奇怪的效果的答案。因此,如果您可以阅读规范,这将极大地帮助您的职业。这是一项后天的技能。那么,让我们继续吧。

搜索PDF文件===使我进入规范的第56页: 11.9.4。严格等于运算符(===),在浏览规范后,我发现:

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

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

没那么快!

我们来检查一下操作数的类型。将它们包裹起来,亲自尝试一下 类型()。我发现 新字符串(“a”) 是一个对象,使用步骤1:return  如果类型不同。

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


Aidiakapi在下面的评论中写道:

从规范

11.2.2新运营商

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

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

 总是返回一个Object,即使是  建设者也是。唉!字符串的值语义(参见步骤11)将丢失。

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


250
2018-05-12 12:58



类型(x)的结果暗示与typeof相同? - Dfr


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


93
2017-12-25 11:17



@David:对。这就是为什么这个答案不准确(甚至是错误的) - Philippe Leybaert
@大卫 var a = {}, b = {};  a == b 返回false。 - nyuszika7h
是的:两个 不同 具有相同类型和值的对象比较错误,即,这个答案是错误的。为什么它有50个赞成? - alexis
我意识到这是旧的,但澄清为什么这个答案仍然“正确”是因为在这个例子中 var a = {}, b = {}; 两者都有 a 和 b 确实都是一个对象,但它们不是 相同 从技术上讲,价值。他们是 不同 实例。请注意,比较实例的行为与比较基元的行为不同。这可能会增加这种混乱。如果使用基本数据类型的实例版本,您将看到类似的比较行为。例如 new String('asdf') 要么 new Number(5)。例如: new Number(5) == new Number(5) 是错误的,即使它们具有相同的价值。 - Norman Breau


我用Firefox测试了这个 萤火 使用这样的代码:

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相同),代码质量也是如此。


88
2018-05-12 12:58



除了类型安全之外,您还需要逻辑正确性 - 有时您希望事情变得简单 == 不同意。 - rpjohnst
现在,当存在实际类型的coersion时,如何进行比较 == 运营商?请记住,那就是性能提升的时候。 - Hubert OG
由于上述原因,为了更快地检查类型不等式,正确测试时的主要差异。 jsfiddle.net/4jhuxkb2 - Doug Morrow


在JavaScript中,它意味着相同的值和类型。

例如,

4 == "4" // will return true

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

84
2017-12-11 14:58





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

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

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

如果是 “a === b” a和b必须是 相同的价值 还有 相同的类型 为了评估为真。

以下面的例子为例

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%的使用场景中,使用哪一个并不重要,但是当你有一天意外行为时,知道差异就很方便了。


73
2018-05-12 12:58



这是关于=== vs ==的比较的详细文章 - Zaheer Ahmed


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

例:

'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

64
2017-09-05 13:53



也, 'string' !== 'number' - Homer


严格相等的Javascript执行流程图/比较'==='

Javascript strict equality

用于非严格相等/比较的Javascript执行流程图'=='

Javascript non equality


61
2017-08-09 16:50



我不明白为什么 string 箭头指向大灰色框,它是否应该表示中断器正在将字符串转换为数字? - vsync
@vsync它指向灰色框内的字符串选项,即字符串 - >#|| NaN的。 Javascript不是类型脚本语言,但基本上它可以有任何类型的变量。因此,它指向灰色框。 - Samar Panda
我只是问是否是为了铸造目的 string 应该被比作一种类型 number,所以中断器会查看字符串应该与什么进行比较并相应地转换字符串? - vsync
大灰盒子是什么 ToNumber 当给定不同的类型时会返回,所以如果给它一个字符串,它将只选择最后一个选项(并将其转换为数字)。 == 使用 ToNumber 只有在这种情况下 string == number 要么 boolean == anything 以上(仅限于 string/boolean)。意即 == 永远不会转换 undefined 要么 null 即使他们在灰色的盒子里。 (任何组合 undefined 要么 null 或两者, == 永远都会回来 true。此外,值是左侧还是右侧无关紧要, == (和 ===)将返回相同的结果。) - user2033427