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




的区别 (24)

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

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

例如,如果您有:

$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

我正在使用JSLint来通过JavaScript,并且在执行诸如比较idSele_UNVEHtype.value.length == 0类的内容时返回了许多建议来替换== (两个等号) === (三个等号)声明。

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

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

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


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

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

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


* 运营商=== vs == *

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

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

var a;
var b = null;

在这里ab没有价值观。然而,0,false和''都是值。所有这些之间的共同点是,它们都是假值,这意味着它们都满足虚假条件。

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

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


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

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


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


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

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

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

但是有一个例外== null检查'is null或undefined'是一种有效的方法:

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

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

jQuery样式指南

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

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

只是

==装置的比较操作数之间 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 

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

例如,

4 == "4" // will return true

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

在典型的脚本中,没有性能差异。 更重要的可能是千元“===”比千元“==”重1 KB这一事实: JavaScript分析器可以告诉您在您的情况下是否存在性能差异。

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


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


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

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

  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.

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

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

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

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

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


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

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

true

是的,根据==一个空字符串是正确的,数字零是同一时间。

它并没有结束,这是另一个:

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

那么这是什么意思?

这意味着==很复杂。

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

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

所以这个故事的寓意是......

让你的生活变得简单。

使用===而不是==

结束。



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关于参考类型的 answer中提出了一个很好的观点。 对于引用类型, =====彼此一致地行动(特殊情况除外)。

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


在这里的答案中,我没有读到关于什么是平等的意思。 有人会说===意味着相同和相同的类型 ,但事实并非如此。 它实际上意味着两个操作数引用相同的对象 ,或者在值类型的情况下,具有相同的值

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

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如果ab具有相同的值且属于同一类型,则返回true

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

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


一个简单的例子是

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

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

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

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

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

CString x;
delete x;

显然在运行时期间有很多未定义的东西......

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


平等比较:

操作者 ==

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

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

平等和类型比较:

操作者 ===

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

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

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

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


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

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

var1 === var2

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

var1 == var2

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

故事的道德启示:

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


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

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





identity-operator