console.log( 0 == '0' ); // true
console.log( 0 == [] ); // true
console.log( [] == '0' ); // false
为什么 JavaScript 会这样评估表达式?
console.log( 0 == '0' ); // true
console.log( 0 == [] ); // true
console.log( [] == '0' ); // false
为什么 JavaScript 会这样评估表达式?
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相比,包含一个数字的数组显然会转换为该数字。然后转到将数字与字符串进行比较的规则,该规则将字符串转换为数字。因此,我们将(0
或1
或..)与(0
或1
或..)进行比较。
这是规范中的歧义吗?不同的实现有什么不同?
在测试完成后https://www.webtoolkitonline.com/javascript-tester.html
2020年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"));
/*
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');
JavaScript 使用类型类型转换在需要它的上下文中将任何值强制转换为布尔值,例如条件和循环。
第一种情况
console.log( 0 == '0');
javascript 使用强制并将两者都转换为 number 和 compares 。现在 0==0 所以返回 true 。
第二种情况
console.log( 0 == [] );
两者都是假的(假值是在布尔上下文中计算时转换为假的值)。所以现在比较 false == false ,返回 true 值。
第 3 种情况
console.log( [] == '0');
[] 是假的,'0' 是字符串,js 无法强制它们转换为可以比较的类型。所以返回 false 。