JavaScript比较运算符:Identity与Equality

JavaScript comparison operators: Identity vs. Equality

我一直在试图理解JavaScript的比较运算符之间的区别:标识和相等。根据我读到的内容,如果使用==检查两个对象的相等性,javascript将尝试找出它们是否是同一类型,如果不是,则尝试将它们转换为同一类型。然而,==的行为方式不同。例如:

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

那么,这些"同一性"操作符和正规的等同性操作符之间有什么区别呢?两者都有什么好处?

性能有差异吗?我认为身份操作符会更快,因为它不进行转换。

另外,当涉及到更复杂的对象(如数组)时,它们有什么不同?最重要的是,关于什么时候应该使用一个公约而不是另一个公约,为什么?


相等运算符将尝试在进行比较之前使数据类型相同。另一方面,Identity运算符要求这两种数据类型作为前提条件相同。

有相当多的其他帖子类似于这个问题。见:

php equality(=double equals)和identity(=triple equals)比较运算符有什么不同?(有一个很好的比较图)
在JavaScript比较中应使用哪个等于运算符(==vs==)?

在实践中,当你想确定一个布尔值是真是假的时候,身份操作符就非常有用了,因为…

1
2
3
4
1 == true     => true
true == true  => true
1 === true    => false
true === true => true

区别在于==、<=、>=和!=将执行类型强制&mdash;例如,强制将字符串计算为数字。==、<==、>==和!==不执行类型强制。他们将把一个字符串与一个数字进行比较,由于字符串"1"与数值1不同,所以结果是假的。

参考资料如下:https://developer.mozilla.org/en/javascript/reference/operators/comparison_operators


=====相同,只是==进行类型转换。

为了向您展示我的意思,这里有一个javascript函数,它的行为与==完全相同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 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
2
3
4
5
6
7
8
9
[1] == true // returns true
'0' == false // returns true
[] == false // returns true
[[]] == false // returns true
[0] == false // returns true

'

\t'
== 0 // returns true

意料之外的结论

1
2
3
4
5
6
7
8
// 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**

具有特殊功能的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 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**

原因是,identity或strict运算符(==)与不进行类型转换相比,这意味着如果两个值没有相同的值和相同的类型,它们就不会被视为相等的。

以下链接中有更清晰的解释:

https://medium.com/@ludico8/identity-vs-equality-battle-of-understanding-vs-758d396e922.hhg396ey9