JavaScript 相等传递性很奇怪

发布于 2024-10-26 15:26:05 字数 538 浏览 5 评论 0原文

我一直在阅读 Douglas Crockford 的 JavaScript:优秀部分,我遇到了这个对我来说没有意义的奇怪例子:

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

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

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

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:

'' == '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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一杯敬自由 2024-11-02 15:26:05
'' == '0' // false

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

0 == '' // true

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

0 == '0' // true

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

false == undefined // false

undefined 值在 JavaScript 中很特殊,不等于除 null 之外的任何值。然而,它是虚假的。

false == null // false

同样,null 很特殊。它仅等于未定义。它也是假的。

null == undefined // true

nullundefined 类似,但不一样。 null 表示什么都没有,而undefined 是未设置或不存在的变量的值。他们的价值观被认为是平等的,这是有道理的。

如果你真的很困惑,请检查这个...

'\n\r\t' == 0

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

Crockford 提出了很多建议,但你不必将它们视为福音。 :)

TJ Crowder 提出了学习ECMAScript 语言规范 了解这些平等测试背后的整个故事。

进一步阅读?

规范

yolpo(关于虚假值)

'' == '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).

0 == '' // true

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

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.

false == undefined // false

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

false == null // false

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

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)

泅渡 2024-11-02 15:26:05

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

'' == '0' 等价于 '' === '0' (两者都是字符串,因此不需要强制转换)。

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

出于同样的原因,0 == '0' 相当于 0 === 0

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

false == null出于同样的原因,相当于 0 === null

null == undefined 是 true,因为规范是这么说的。

感谢您提出这个问题。经过研究,我对 == 的理解要好得多。

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.

稍尽春風 2024-11-02 15:26:05

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

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**
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文