JavaScript 相等传递性很奇怪

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5447153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 17:13:43  来源:igfitidea点击:

JavaScript equality transitivity is weird

javascriptcomparison-operatorsequivalencetransitivity

提问by Hristo

I've been reading Douglas Crockford's JavaScript: The Good Parts, and I came across this weird example that doesn't make sense to me:

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

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

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

The author also goes on to mention "to never use ==and !=. Instead, always use ===and !==". However, he doesn't explain why the above behavior is exhibited? So my question is, why are the above results as they are? Isn't transitivity considered in JavaScript?

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

采纳答案by alex

'' == '0' // false

The left hand side is an empty string, and the right hand side is a string with one character. They are false because it is making a comparison between two un identical strings (thanks Niall).

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

0 == '' // true

Hence, why this one is true, because 0is falsyand the empty string is falsy.

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

0 == '0' // true

This one is a bit trickier. The spec states that if the operands are a string and a number, then coerce the string to number. '0'becomes 0. Thanks smfoote.

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

false == undefined // false

The value undefinedis special in JavaScript and is not equal to anything else except null. However, it is falsy.

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

false == null // false

Again, nullis special. It is only equal to undefined. It is also falsy.

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

null == undefined // true

nulland undefinedare similar, but not the same. nullmeans nothing, whilst undefinedis the value for a variable not set or not existing. It would kind of make sense that their values would be considered equal.

nullundefined是相似的,但不一样。null意味着什么undefined而是未设置或不存在的变量的值。他们的价值观被视为平等是有道理的。

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

如果您真的想感到困惑,请检查此...

'\n\r\t' == 0

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

仅由空格组成的字符串被认为等于 0。

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

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

T.J. Crowdermakes an excellent suggestion of studying the ECMAScript Language Specificationto know the whole story behind these equality tests.

TJ Crowder提出了一个很好的建议,即学习ECMAScript 语言规范以了解这些相等性测试背后的整个故事。

Further Reading?

进一步阅读?

The spec.

规格

yolpo (on falsy values)

yolpo(假值)

回答by smfoote

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

这个问题的答案与 JavaScript 如何处理强制有关。在 的情况下==字符串被强制为数字。所以:

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

'' == '0'等价于'' === '0'(两者都是字符串,所以不需要强制)。

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

0 == ''等价于0 === 0因为字符串''变成了数字0( math.abs('') === 0)。

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

0 == '0'等价于0 === 0同样的原因。

false == undefinedis equivalent to 0 === undefinedbecause JavaScript coerces booleans to be numbers when types don't match

false == undefined等价于0 === undefined因为 JavaScript 在类型不匹配时将布尔值强制为数字

false == nullis equivalent to 0 === nullfor the same reason.

false == null等价于0 === null同样的原因。

null == undefinedis true because the spec says so.

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

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

感谢您提出这个问题。我==对它的了解要好得多。

回答by Luis Perez

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

您实际上可以编写一个行为与该行为完全相同的 JavaScript 函数,这样您就可以==深入了解它的行为方式。

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

回答by ludico8

The reason is that identity or strict operator (===), it compares with no type conversion, that means if both values doesn't have the same value and the same type, they won't be considered equal.

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

take a look this link, it takes you out of doubt: easy way to understand how identity operator works

看看这个链接,它会让你毫无疑问: 了解身份运算符如何工作的简单方法