2011-03-27 64 views
32

我一直在读Douglas Crockford's JavaScript: The Good Parts,我碰到这个奇怪的例子,没有任何意义,我就来了:的JavaScript平等及物性是怪异

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

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

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

+2

回答这个问题的最好方法是阅读规范:http://www.ecma-international.org/publications/standards/Ecma-262.htm如果你真的想知道本质为什么上面的陈述是他们的方式,真的没有更好的办法。准备好在某些地方可能会有点吝啬,但是如果你问这样的问题,这是非常值得的。 – 2011-03-27 04:35:23

+0

@ T.J。 Crowder非常好的建议(+1),我把这个链接编辑到我的答案中,希望你不介意。 – alex 2011-03-27 04:41:00

+0

@alex:当然不是。 :-) – 2011-03-27 04:42:37

回答

25
'' == '0' // false 

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

0 == '' // true 

因此,为什么这一个是真的,因为0falsy和空字符串是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装置没什么,而undefined为未设置或不存在的变量的值。如果他们的价值被认为是平等的,那将是有道理的。

如果你想成为真糊涂,看看这个...

'\n\r\t' == 0 

只包含空格的字符串被认为是等于0

道格拉斯克罗克福德使得很多的建议,但你不必把他们当作福音。 :)

T.J. Crowder提供了一个很好的建议,研究ECMAScript Language Specification知道这些平等测试背后的整个故事。

进一步阅读?

The spec

yolpo (on falsy values)

+2

*“道格拉斯克罗克福德提出了很多建议,但你不必把它们当作福音。”*说得好。克罗克福德是一个很聪明的人,他对这种语言有着深刻的思考,所以很值得一读他提出的观点和他所提出的观点。然后得出你自己的结论。 – 2011-03-27 04:44:43

+0

@alex ...在你的第三段中,以“这一个有点棘手”开头,你不是说'=='检查类型吗? – Hristo 2011-03-27 05:44:42

+0

@Hristo'=='不检查类型,只是值。 – alex 2011-03-27 11:40:09

7

回答这个问题都有用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是真实的,因为规范是这样说的。

感谢您提出这个问题。我对==的理解对于研究它更好。

-1

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

看看这个链接,它需要你出疑问: easy way to understand how identity operator works

3

实际上,你可以写一个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**