41

我一直在阅读Douglas Crockford 的JavaScript: The Good Parts,我遇到了这个对我来说没有意义的奇怪示例:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == undefined  // false
false == null       // false
null == undefined   // true

作者还继续提到“永远不要使用==and !=。相反,总是使用===and !==”。但是,他没有解释为什么会出现上述行为?所以我的问题是,为什么上面的结果是这样的?JavaScript 中没有考虑传递性吗?

4

3 回答 3

33
'' == '0' // false

左边是空字符串,右边是一个字符的字符串。它们是错误的,因为它正在对两个不同的字符串进行比较(感谢Niall)。

0 == '' // true

因此,为什么这个是真的,因为0它是的,而空字符串是的。

0 == '0' // true

这个有点棘手。规范规定,如果操作数是字符串和数字,则将字符串强制转换为数字。'0'变成0. 谢谢smfoote

false == undefined // false

该值undefined在 JavaScript 中是特殊的,不等于除null. 然而,它是虚假的。

false == null // false

再次,null是特殊的。它只等于undefined。它也是虚假的

null == undefined // true

null and undefined are similar, but not the same. null means nothing, whilst undefined is the value for a variable not set or not existing. It would kind of make sense that their values would be considered equal.

If you want to be really confused, check this...

'\n\r\t' == 0

A string consisting only of whitespace is considered equal to 0.

Douglas Crockford makes a lot of recommendations, but you don't have to take them as gospel. :)

T.J. Crowder makes an excellent suggestion of studying the ECMAScript Language Specification to know the whole story behind these equality tests.

Further Reading?

The spec.

yolpo (on falsy values)

于 2011-03-27T04:14:34.480 回答
8

The answer to this question has to do with how JavaScript handles coercion. In the case of ==, strings are coerced to be numbers. Therefore:

'' == '0' is equivalent to '' === '0' (both are strings, so no coercion is necessary).

0 == '' is equivalent to 0 === 0 because the string '' becomes the number 0 (math.abs('') === 0).

0 == '0' is equivalent to 0 === 0 for the same reason.

false == undefined is equivalent to 0 === undefined because JavaScript coerces booleans to be numbers when types don't match

false == null is equivalent to 0 === null for the same reason.

null == undefined is true because the spec says so.

Thanks for asking this question. My understanding of == is much better for having researched it.

于 2014-02-27T05:13:54.857 回答
4

You can actually write a JavaScript function that behaves exactly like == that should give you some insight into how it behaves.

To show you what I mean here is that function:

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

As you can see == has a lot of complicated logic for type conversion. Because of that it's hard to predict what result you are going to get.

Here are some examples of some results you wouldn't expect:

Unexpected Truths

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

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

Unexpected Conclusions

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

Objects with Special Functions

// 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**
于 2016-08-09T17:41:15.763 回答