JavaScript比较运算符:恒等与相等

22

我一直在试图理解JavaScript的比较运算符:恒等和相等的区别。根据我的阅读,如果你使用==检查两个对象的相等性,JavaScript会尝试确定它们是否是相同的类型,如果不是,则尝试将它们转换为相同的类型。然而,===不以同样的方式行事。所以举个例子:

var n = "1";
console.log(n==1);        // outputs true
console.log(n===1);       // outputs false

那么“identity”运算符和常规的等式运算符之间有什么区别?拥有两者的好处是什么?

它们在性能上有区别吗?我认为“identity”运算符会更快,因为它不进行转换。

此外,当涉及到更复杂的对象(例如数组)时,它们如何不同?最重要的是,约定是什么时候应该使用其中一个,为什么?


1
在这里,我提供了一个 JavaScript 中等于运算符的真值表:https://dev59.com/Z3RC5IYBdhLWcg3wROpQ#7446163 - CuongHuyTo
4个回答

34

在进行比较之前,等号运算符将尝试使数据类型相同。另一方面,恒等运算符要求两个数据类型先前必须相同。

有很多其他类似这个问题的帖子。请参见:

PHP 等于运算符(== 双等号)和恒等运算符(=== 三等号)的区别是什么?(有一个不错的比较图表)
JavaScript 比较中应该使用哪个等号运算符(== vs ===)?

在实际使用中,当你想确保布尔值为 true 或 false 时,恒等运算符非常有用,因为...

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

17

明白了...所以它就像我上面概述的那样简单。身份运算符不检查类型,但相等运算符会检查。 - Hristo
2
关于何时使用哪一个; Douglas Crockford几乎总是更好地使用===和!==操作符。==和!=运算符会进行类型转换。特别是,不要使用==来与假值进行比较. - no.good.at.coding
@no.good.at.coding:Crockford 是教条主义者,在这种情况下是错误的。在两个操作数保证为相同类型的情况下(例如,在 typeof 比较中,如 typeof foo == "undefined"),使用 === 而不是 == 没有任何优势,因为它们被指定使用完全相同的步骤。 - Tim Down
1
@Tim Down,在您的示例中,这是不必要的,但它是否错误?使用 === 有什么缺点吗?除了这个例子之外,我唯一能想到的是强制显式转换。 - hyperslug
2
但是 '<==' 和 '>==' 不存在。 - WGH
显示剩余2条评论

12

===== 一样,只是 == 做类型转换。

为了让你明白我的意思,这里有一个 JavaScript 函数,它的行为与 == 完全相同:

// loseEqual() behaves just like `==`
function loseEqual(x, y) {
    // notice the function only uses "strict" operators 
    // like `===` and `!==` to do comparisons

    if(typeof y === typeof x) return y === x;

    if(typeof y === "function" || typeof x === "function") return false;

    // 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 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;

    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

这个函数应该有助于解释为什么人们一直说你不应该使用 ==

正如您所见,== 具有许多复杂的类型转换逻辑。因此很难预测您将得到什么结果 - 这可能导致错误。

以下是一些您不会预期到的结果示例:

意外的真相

[1] == true // returns true
'0' == false // returns true
[] == false // returns true
[[]] == false // returns true
[0] == false // returns true

'\r\n\t' == 0 // returns true

意外的结论

// IF an empty string '' is equal to the number zero (0)
'' == 0 // return true

// AND the string zero '0' is equal to the number zero (0)
'0' == 0 // return true

// THEN an empty string must be equal to the string zero '0'
'' == '0' // returns **FALSE**
具有特殊功能的对象
// Below are examples of objects that
// implement `valueOf()` and `toString()`

var objTest = {
    toString: function() {
        return "test";
    }
};

var obj100 = {
    valueOf: function() {
        return 100;
    }
};

var objTest100 = {
    toString: function() {
        return "test";
    },
    valueOf: function() {
        return 100;
    }
};

objTest == "test" // returns true
obj100 == 100 // returns true
objTest100 == 100 // returns true

objTest100 == "test" // returns **FALSE**

0

特别需要注意的是等式和恒等运算符。等式运算符将尝试强制转换(转换)操作数为相同类型以评估相等性。这是一个方便的功能,只要您知道它正在发生即可。此代码块显示了等式运算符的实际应用。

let firstVal = 5;
let secondVal = "5";
if (firstVal == secondVal) {
console.log("They are the same");
} else {
console.log("They are NOT the same");
}

此脚本的输出如下:

它们是相同的

JavaScript 将两个操作数转换为相同的类型并进行比较。实质上,等号运算符测试值是否相同,而不考虑它们的类型。

如果您想要测试确保值和类型都相同,则需要使用恒等运算符(===,三个等号,而不是等号运算符的两个等号)。

let firstVal = 5;
let secondVal = "5";
if (firstVal === secondVal) {
console.log("They are the same");
} else {
console.log("They are NOT the same");
}

在这个例子中,身份运算符将认为这两个变量是不同的。该运算符不会强制转换类型。此脚本的结果如下所示:

它们不相同


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接