提问



我正在使用JSLint来通过JavaScript,当做比较idSele_UNVEHtype.value.length == 0这样的事情时,它返回了很多建议用===(三个等号)替换==(两个等号)在if陈述中。[149]


==替换为===是否有性能优势?


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


如果没有进行类型转换,那么性能是否会超过==?

最佳参考


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


参考:Javascript教程:比较运算符[150]


==运算符将在执行任何必要的类型转换后比较 。 ===运算符将进行转换,因此如果两个值不相同,===将只返回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


特殊情况是,当您将文字与评估为相同文字的对象进行比较时,由于其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[155]

其它参考1


使用==运算符( 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


使用===运算符(标识)


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


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


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

其它参考2


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


所以,让我们采取以下代码:


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

其它参考3


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


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





var1 === var2




   使用===进行JavaScript相等测试时,一切都按原样。在评估之前没有任何东西被转换。









var1 == var2




   使用==进行JavaScript相等测试时,有些
  发生了时髦的转换。








   故事的道德:

  
   使用===除非您完全理解
  使用==进行转换。



其它参考4


让我补充一下这个忠告:


如有疑问,请阅读规范! [157]


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


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


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



   11.9.6严格的等式比较算法

  比较x === y,其中x和y是值,产生 true false 。这样的比较如下进行:

     1。如果Type(x)与Type(y)不同,则返回 false

     2。如果Type(x)未定义,则返回 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)是布尔值,如果x和y都 true 或两者都 false ,则返回 true ;否则,返回 false

     13。如果x和y引用同一个对象,或者它们引用相互连接的对象,则返回 true (参见13.1.2)。否则,请返回 false



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


没那么快!


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


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





Aidiakapi在下面的评论中写道:



  从规范

  
   11.2.2新运营商:

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

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



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


这最终意味着:新字符串(a)!==a

其它参考5


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

其它参考6


我使用Firebug在Firefox中测试了这个,使用如下代码:[158]


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

其它参考7


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


例如,


4 == "4" // will return true





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

其它参考8


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


让我们采取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%的使用场景中,它不管你使用哪一个都很重要,但是当你有一天出现意想不到的行为时,知道差异就很方便了。

其它参考9


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


示例:


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

其它参考10


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


[159]


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


[160]

其它参考11


为什么==如此难以预测?


将空字符串""与数字0进行比较时,您会得到什么?


true


是的,根据==是空的字符串,数字0是同一时间。


它不会在那里结束,这是另一个:


'0' == false // true


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


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


然后用字符串怪异


[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!


让我再说一遍:


(A == B) && (B == C) // true
(A == C) // **FALSE**


而这只是你用原语获得的疯狂东西。


当你对物体使用==时,这是一个全新的疯狂程度。


此时你可能想知道......


为什么会这样?


好吧,这是因为不像三等于(===,它只是检查两个值是否相同。


==做了 其他一些东西


它具有对函数的特殊处理,对空值的特殊处理,未定义,字符串,您可以对其进行命名。


它变得很古怪。


事实上,如果你试图编写一个执行==功能的函数,它会看起来像这样:


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();
}


那是什么意思?


这意味着==很复杂。


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


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


故事的寓意是......


让你的生活变得简单。


使用===代替==


结束。

其它参考12


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

其它参考13


它意味着没有类型强制的平等
类型强制意味着JavaScript不会自动将任何其他数据类型转换为字符串数据类型


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 

其它参考14


在典型的脚本中,没有性能差异。更重要的可能是千分之一===是1比KB的重量大于千分之一==:) JavaScript分析器可以告诉您在您的情况下是否存在性能差异。


但就我个人而言,我会做JSLint所说的。这个建议不是因为性能问题,而是因为类型强制意味着('\t\r\n' == 0)是真的。

其它参考15


平等比较运算符==令人困惑,应该避免使用。


如果您有必要,请记住以下3件事:



  1. 它不具有传递性:(a == b)和(b == c)不会导致(a == c )

  2. 它与否定相互排斥:(a == b)和(a!= b)总是保持相反的布尔值,所有a和b。

  3. 如有疑问,请记下以下真值表:



JAVASCRIPT中的等号运算符真值表



  • 表中的每一行都是一组3个相互相等的值,这意味着它们中的任何2个值都相等,使用等于==符号*



** STRANGE:请注意,第一列中的任何两个值在这个意义上都不相等。**


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

其它参考16


在您的使用中,这两个操作之间不可能有任何性能差异。没有要进行类型转换,因为两个参数已经是同一类型。两个操作都将进行类型比较,然后进行值比较。

其它参考17


是的!这很重要。


===运算符在javascript 中检查值以及键入,其中==运算符只检查值(如果需要,则进行类型转换)





你可以轻松测试它。将以下代码粘贴到HTML文件中,然后在浏览器中打开它


<script>

function onPageLoad()
{
    var x = "5";
    var y = 5;
    alert(x === 5);
};

</script>

</head>

<body onload='onPageLoad();'>


您将在警报中获得 false 。现在将onPageLoad()方法修改为alert(x == 5);,您将获得 true

其它参考18


===运算符检查值以及变量的类型是否相等。


==运算符只是检查变量的值是否相等。

其它参考19


这是一项严格的检查测试。


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


例如,如果您有:


$a = 0;


然后:


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


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


所以与上面相同,但严格的测试:


$a = 0;

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

其它参考20


JSLint有时会给你修改内容的不切实际的理由。如果类型已经相同,=====具有完全相同的性能。


仅当类型不相同时才更快,在这种情况下它不会尝试转换类型但直接返回false。


因此,恕我直言, JSLint可能用于编写新代码,但应该不惜一切代价避免无用的过度优化。


意思是,当你知道一个只能是一个字符串的事实时,没有理由在if (a == 'test')这样的支票中改变=====


修改大量代码会浪费开发人员和审阅者的时间并且什么都不会实现。

其它参考21


只是


==表示操作数 type conversion之间的比较


&安培;


===表示操作数之间比较,不含 type conversion


javaScript中的类型转换意味着javaScript会自动将任何其他数据类型转换为字符串数据类型。


例如:


123=='123'   //will return true, because JS convert integer 123 to string '123'
             //as we used '==' operator 

123==='123' //will return false, because JS do not convert integer 123 to string 
            //'123' as we used '===' operator 

其它参考22


一个简单的例子是


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

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

其它参考23


前两个答案都提到==表示平等,===表示身份。不幸的是,这种说法不正确。


如果==的两个操作数都是对象,则比较它们以查看它们是否是同一个对象。如果两个操作数都指向同一个对象,则等于运算符返回true。除此以外,
两者并不相等。


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


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


这就是说:如果==的两个操作数都是对象,==的行为与===相同,这也意味着身份。这两个运算符的本质区别在于类型转换。==在检查相等性之前进行转换,但是===没有。

其它参考24


根据经验,我通常会使用===而不是==(和!==而不是!=


原因在上面的答案中解释,道格拉斯克罗克福德也非常清楚(JavaScript:The Good Parts)。


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


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


例如,jQuery 1.9.1使用此模式43次,因此JSHint语法检查程序甚至提供eqnull放松选项。[163]


来自jQuery样式指南:[164]



  应使用严格的等式检查(===)以支持==。唯一的
  异常是通过null检查undefined和null。


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


其它参考25


来自核心javascript参考[165]



  ===如果操作数严格相等则返回true(见上文)
  没有类型转换。


其它参考26


问题是你很容易遇到麻烦,因为JavaScript有很多隐含的转换意味着......


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


这很快就会成为一个问题。隐式转换为邪恶的最佳样本可以从MFC/C ++中的代码中获取,由于从CString到HANDLE的隐式转换,它实际上将被编译,这是一个指针typedef类型... [166]


CString x;
delete x;


显然在运行时非常未定义的东西......


谷歌在C ++和STL中进行隐式转换,以获得反对它的一些论据...... [167]

其它参考27


平等比较:


接线员==


当两个操作数相等时返回true。在比较之前,操作数被转换为相同的类型。


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


平等和类型比较:


接线员===


如果两个操作数相等且类型相同,则返回true。一般来说
如果你比较这种方式会更好更安全,因为没有幕后类型的转换。


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

其它参考28


* 运营商=== vs == *


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

其它参考29


null和undefined是虚无,也就是说,


var a;
var b = null;


这里ab没有值。然而,0,false和都是值。有一件事很常见所有这些都是它们都是假值,这意味着它们都满足虚假条件。


因此,0,false和一起形成一个子组。而另一方面,null& undefined形成第二个子组。检查下图中的比较。 null和undefined会相等。其他三个将彼此相等。但是,它们都被视为JavaScript中的虚假条件。





这与任何对象(如{},数组等)相同,非空字符串&布尔值为true都是条件。但是,他们都不平等。