为什么“0” == [] 是假的?

IT技术 javascript
2021-02-20 19:38:10

console.log( 0 == '0' );     // true
console.log( 0 == [] );     // true 
console.log( [] == '0' );    // false

为什么 JavaScript 会这样评估表达式?

4个回答

JavaScript 会在使用双等号运算符 ( ==)时尝试强制类型规范中的确切细节:第 11.9.3 节:抽象平等比较算法

示例 1:

console.log( 0 == '0' );     // true

JavaScript 将字符串强制转换为数字0,因此0 == 0.

示例 2:

console.log( 0 == [] ); // true

与数字进行比较时,空数组的“ToPrimitive”值为零。所以这一个减少到0 == 0

示例 3:

 console.log( [] == '0' ); // false
 console.log( [] == '' ); // true

虽然第一个看起来与前面的示例非常相似,但两边都不是数字。乍一看,这似乎是一个truthy比较,但[]不是八个之一falsy
证明这[]是真的,但是''是假的:

 console.log( [] ? true : false ); // true
 console.log( '' ? true : false ); // false

在任何理智的语言,上面的两个语句将暗示[] == ''false但正如我们之前看到的,在 JavaScript 中并非如此!

无法解释,使用时[]转换为false==

 console.log( [] == true ); // false
 console.log( [] == false ); // true

结论:双方都转换为布尔值,但不是通过“正常”“真/假”规则(会转换[]true,因为它不是八个假值之一)。相反,在使用时[]转换为false==

 console.log( [] == '0' ); // `false == true`, so false
 console.log( [] == '' ); // `false == false`, so true

示例 4:

 console.log( [0] == '' ); // false
 console.log( [1] == '' ); // false

这可能EITHER表明长度的阵列(的1),这是“truthy”,进行比较'',这是“falsy”,所以true == false,这是false或者它可能表明没有合适的类型转换,这是规范中的情况 (10),所以false. 但请参阅示例 5,这似乎不适合任何一种可能性。

示例 5:

 console.log( [0] == '0' ); // true
 console.log( [0] == '1' ); // false
 console.log( [1] == '1' ); // true
 console.log( [1] == '0' ); // false
 console.log( [2] == '2' ); // true
 console.log( [1] == '2' ); // false

令人惊讶的是,与非空 string相比,包含一个数字的数组显然会转换为该数字然后转到将数字与字符串进行比较的规则,该规则将字符串转换为数字。因此,我们将(01或..)与(01或..)进行比较。
这是规范中的歧义吗?不同的实现有什么不同?
在测试完成后https://www.webtoolkitonline.com/javascript-tester.html2020年10月27,在Chrome在Windows 10的电脑,使用alert代替console.log

示例 6:

如果以上所有内容都不能说服您不再使用==,请考虑:

var a = [];
console.log( a == a ); // true

但:

console.log( [] == [] ); // false

规范中的 9 条类型转换规则都不适用,所以这是案例 10:它们不是同一个对象,即使它们都没有任何内容。它们是空数组的两个不同实例。


总之,这就是为什么使用三重等号通常更安全的原因,它检查类型和相等性。

下面是一个方便的说明(用于测试真实性的情况):

function truthyOrFalsy(val) {
    return val ? "Truthy" : "Falsy";
}

console.log("empty array:", truthyOrFalsy([]));
console.log("number zero:", truthyOrFalsy(0));
console.log("string with a zero character:", truthyOrFalsy("0"));

@TheChetan:我的建议是不要了解它,而是遵循 Douglas Crockford 的建议,总是===用来避免不得不处理这种经常出现的古怪行为。
2021-04-26 19:38:10
哪里可以读到这个?关于这种转换是如何发生的?
2021-05-05 19:38:10
-1 “双方都是假的……一个是假的,另一个不是” 不,JavaScript 中的所有列表都是真的,即使是空列表。虚假真的与它没有太大关系。
2021-05-05 19:38:10
所有三个示例都有轻微到非常误导性:1) 两个操作数都转换为数字,如您所见,使用16 == "0x10"NaN != "NaN"2) Truthy/falsy 与此无关;事实上[] 真实的。两者都再次转换为数字,您可以再次使用16 == ["0x10"]. 3)再次真/假与它无关。两者都转换为字符串,如您所见[1,2] == '1,2'空数组被转换为空字符串,它不等于包含 1 的字符串0
2021-05-05 19:38:10
@TheChetan TruthyFalsey上MDN是一个良好的开端。关于这个混淆主题的 stackoverflow 也有大量问题。
2021-05-07 19:38:10
/*
If Type(x) is Number and Type(y) is String,
return the result of the comparison x == ToNumber(y).
*/
console.log( 0 == '0');

/*
If Type(x) is either String or Number and Type(y) is Object,
return the result of the comparison x == ToPrimitive(y).
*/
console.log( 0 == [] );

/*
If Type(x) is Object and Type(y) is either String or Number,
return the result of the comparison ToPrimitive(x) == y.
*/
console.log( [] == '0');

来源:http : //es5.github.io/#x11.9.3

Truthy 和 Falsy 除了类型之外,每个值也有一个固有的布尔值,通常称为真值或假值。有些规则有点奇怪,因此在调试 JavaScript 应用程序时理解概念和比较的影响会有所帮助。

以下值始终为假:

  • 错误的
  • 0(零)
  • '' 或 ""(空字符串)
  • 空值
  • 不明确的
  • NaN(例如 1/0 的结果)

其他一切都是真实的。那包括:

  • '0'(包含单个零的字符串)
  • 'false'(包含文本“false”的字符串)
  • [](一个空数组)
  • {}(空对象)
  • function(){}(“空”函数)

使用 == 松散相等比较真值和假值时可能会出现意外情况:

参见宽松平等比较表

与 == 的松散相等比较表

在 JS 中:[] != [] 和 {} != {}
2021-05-10 19:38:10

JavaScript 使用类型类型转换在需要它的上下文中将任何值强制转换为布尔值,例如条件和循环。

第一种情况

console.log( 0 == '0'); 

javascript 使用强制并将两者都转换为 number 和 compares 。现在 0==0 所以返回 true 。

第二种情况

console.log( 0 == [] );

两者都是假的(假值是在布尔上下文中计算时转换为假的值)。所以现在比较 false == false ,返回 true 值。

第 3 种情况

console.log( [] == '0'); 

[] 是假的,'0' 是字符串,js 无法强制它们转换为可以比较的类型。所以返回 false 。

该文档说它适用于布尔上下文。== 不是布尔上下文。
2021-05-02 19:38:10
“例如条件和循环”——这既不是条件也不是循环。它是一个等号运算符。第一种情况将转换'0'为数字而不是字符串。第二种情况会将数组转换为数字。第三种情况将数组转换为字符串并进行比较。ecma-international.org/ecma-262/5.1/#sec-11.9.3
2021-05-17 19:38:10