【问题标题】:Why is "0" == [] false? [duplicate]为什么“0”== [] 是假的? [复制]
【发布时间】:2020-10-28 03:36:21
【问题描述】:

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

为什么 JavaScript 会这样计算表达式?

【问题讨论】:

  • 数字0是假的,字符串"0"不是。
  • 因为真('0')不假([])
  • Boolean([]) 返回 true ,而不是 false
  • 出于与[] == false 和![] == false 相同的原因。 ¯\_(ツ)_/¯
  • 1.在 SO 2 上询问有关 javascript 转换的问题。利润

标签: javascript


【解决方案1】:

JavaScript 会在使用双等号运算符 (==) 时尝试强制类型。规范中的详细信息:sec 11.9.3: Abstract Equality Comparison Algorithm。

示例 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 values 之一。
证明[] 是真的,但'' 是假的:

 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) 的 长度 是“真实的”,与 '' 比较是“虚假的” ",所以true == false,即false。 OR 它可能表示没有合适的类型转换,即规范中的 case (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

令人惊讶的是,当与非空字符串进行比较时,包含一个数字的数组显然会转换为该数字。然后转到将数字与字符串进行比较的规则,该规则将字符串转换为数字。因此,我们将(0 或 1 或 ..)与(0 或 1 或 ..)进行比较。
这是规范中的歧义吗?不同的实现有区别吗?
测试于 2020 年 10 月 27 日在 https://www.webtoolkitonline.com/javascript-tester.html 在 Windows 10 电脑上的 Chrome 中完成,使用 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 Truthy 和 Falsey 在 MDN 上是一个很好的起点。关于这个混淆主题的 stackoverflow 也有大量问题。
  • @TheChetan:我的建议是不要去了解它,而是遵循 Douglas Crockford 的建议,始终使用 === 以避免不得不处理这种经常出现的古怪行为。
  • -1 "双方都是假的......一个是假的,另一个不是" 不,JavaScript 中的所有列表都是真的,即使是空列表。虚假真的与它没有太大关系。
  • 所有三个示例都有轻微的误导性:1) 两个操作数都转换为数字,正如您在16 == "0x10" 或NaN != "NaN" 中看到的那样。 2)真假无关;事实上[]是真实的。两者都再次转换为数字,您可以再次使用16 == ["0x10"] 查看。 3)再次,真/假与它无关。两者都转换为字符串,正如您在[1,2] == '1,2' 中看到的那样;空数组转换为空字符串,不等于包含一个0的字符串。
【解决方案2】:
/*
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

【讨论】:

    【解决方案3】:

    真假 除了类型之外,每个值还具有固有的布尔值,通常称为真值或假值。有些规则有点奇怪,因此了解概念和比较效果有助于调试 JavaScript 应用程序。

    以下值总是假的:

    • 假
    • 0(零)
    • '' 或 ""(空字符串)
    • 空
    • 未定义
    • NaN(例如 1/0 的结果)

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

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

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

    查看松散等式比较表

    【讨论】:

    • 在 JS 中:[] != [] 和 {} != {}
    【解决方案4】:

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

    第一种情况

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

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

    第二种情况

    console.log( 0 == [] );
    

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

    第三种情况

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

    [] 是 falsy 并且 '0' 是 string ,js 无法强制它们转换为可以比较的类型。所以返回 false 。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-01
    • 2013-11-26
    • 2014-02-06
    • 1970-01-01
    相关资源
    最近更新 更多