JavaScript等同传递性很奇怪

时间:2011-03-27 04:09:36

标签: javascript comparison-operators equivalence transitivity

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

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

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

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

4 个答案:

答案 0 :(得分:30)

'' == '0' // false

左侧是空字符串,右侧是带有一个字符的字符串。它们是错误的,因为它在两个不相同的字符串之间进行比较(感谢Niall)。

0 == '' // true

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

0 == '0' // true

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

false == undefined // false

undefined在JavaScript中很特殊,除了null之外不等于其他任何内容。但是,它是 falsy

false == null // false

同样,null很特别。它只等于undefined。它也是 falsy

null == undefined // true

nullundefined相似,但不一样。 null表示 nothing ,而undefined是未设置或不存在的变量的值。将他们的价值观视为平等是有道理的。

如果你真的很困惑,请检查一下......

'\n\r\t' == 0

仅包含空格的字符串被视为等于0.

道格拉斯·克罗克福德提出了很多建议,但你不必将它们视为福音。 :)

T.J. Crowder提出了一个很好的建议,即研究ECMAScript Language Specification以了解这些平等测试背后的全部故事。

进一步阅读?

The spec

yolpo (on falsy values)

答案 1 :(得分:8)

这个问题的答案与JavaScript如何处理强制有关。如果是==strings are coerced to be numbers。因此:

'' == '0'相当于'' === '0'(两者都是字符串,因此不需要强制)。

0 == ''相当于0 === 0,因为字符串''变为数字0math.abs('') === 0)。

出于同样的原因,

0 == '0'相当于0 === 0

false == undefined相当于0 === undefined,因为JavaScript在类型不匹配时强制将布尔值作为数字

出于同样的原因,

false == null相当于0 === null

null == undefined是正确的,因为规范是这样说的。

感谢您提出这个问题。我对==的理解对于研究它来说要好得多。

答案 2 :(得分:4)

你实际上可以编写一个与==完全相同的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**

答案 3 :(得分:-1)

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

看一下这个链接,它让你毫无疑问: easy way to understand how identity operator works