为了账号安全,请及时绑定邮箱和手机立即绑定

空数组似乎同时等于true和false。

空数组似乎同时等于true和false。

肥皂起泡泡 2019-07-27 15:15:27
空数组似乎同时等于true和false。空数组是真,但它们也等于false。var arr = [];console.log('Array:', arr);if (arr) console.log("It's true!");if (arr == false) console.log("It's false!");if (arr && arr == false) console.log("...what??");我想这是由于等式运算符所操作的隐式转换。有人能解释幕后发生了什么吗?
查看完整描述

3 回答

?
炎炎设计

TA贡献1808条经验 获得超4个赞

你在这里测试不同的东西。

if (arr)调用对象(Array是JS中对象的实例)将检查对象是否存在,并返回true/false。

当你打电话if (arr == false)你比较价值这个物体和原语false价值。在内部,arr.toString()调用,它返回空字符串。"".

这是因为toString调用数组返回Array.join()空字符串是JavaScript中的假值之一。



查看完整回答
反对 回复 2019-07-28
?
一只名叫tom的猫

TA贡献1906条经验 获得超3个赞

关于这一行:

if (arr == false) console.log("It's false!");

也许这些会有帮助:

console.log(0 == false) // trueconsole.log([] == 0) // trueconsole.log([] == "") // true

我认为正在发生的是布尔值false被迫0用于与物体(左手边)进行比较。对象被强制为字符串(空字符串)。然后,空字符串也被胁迫成一个数字,即零。所以最后的比较是0 == 0,也就是true.

编辑:看见规范的这一部分有关此操作的详细信息。

下面是正在发生的事情,从规则1开始:

1.如果类型(X)与类型(Y)不同,则转到步骤14。

下一个适用的规则是#19:

19.如果类型(Y)是布尔型,则返回比较x=ToNumber(Y)的结果。

结果ToNumber(false)0,我们现在有:

[] == 0

同样,规则1告诉我们跳到第14步,但实际适用的下一步是#21:

21.如果Type(X)是Object,Type(Y)是字符串或数字,则返回比较ToPrimitive(X)=y的结果。

结果ToPrimitive([])是空字符串,所以我们现在有:

"" == 0

同样,规则#1告诉我们跳到步骤#14,但实际适用的下一步是#17:

17.如果Type(X)是String,Type(Y)是Number,则返回比较ToNumber(X)=y的结果。

结果ToNumber("")0,这就给我们留下了:

0 == 0

现在,这两个值都具有相同的类型,因此这些步骤从#1一直持续到#7,如下所示:

7.如果x是与y相同的数字值,则返回true。

所以,我们回来true.

简言之:

ToNumber(ToPrimitive([])) == ToNumber(false)



查看完整回答
反对 回复 2019-07-28
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

解释为什么ToPrimitive([])回报""对于“为什么”这个问题,有两种可能的答案是值得考虑的。第一种回答是:“因为规范上说这就是JavaScript的行为方式。”在ES5规范中,第9.1节,它将ToPrimitive的结果描述为对象的默认值:

对象的默认值是通过调用对象的[DefaultValue]内部方法来检索的,并传递可选的提示PreferredType。

第8.12.8节描述[[DefaultValue]]方法。此方法以“提示”作为参数,提示可以是字符串,也可以是数字。若要简化此事项,请不要使用某些细节,如果提示为字符串,则[[DefaultValue]]返回toString()如果存在并返回原语值,则返回valueOf()..如果提示为数字,则toString()valueOf()是相反的,所以valueOf()首先调用,如果它是原语,则返回它的值。因此,是否[[DefaultValue]]返回toString()valueOf()取决于对象的指定PreferredType以及这些函数是否返回原语值。

默认valueOf()对象方法只返回对象本身,这意味着除非类重写默认方法,valueOf()只返回对象本身。情况就是这样Array[].valueOf()返回对象[]本身。因为Array对象不是原语,[[DefaultValue]]提示无关:数组的返回值将是toString().

引用大卫弗拉纳根JavaScript:权威指南顺便说一句,这是一本很棒的书,每个人都应该首先找到这些问题的答案:

此对象到数字转换的详细信息解释了为什么空数组转换为数字0,以及为什么具有单个元素的数组也可以转换为数字。数组继承了返回对象而不是原始值的默认值()方法,因此数组到数字的转换依赖于toString()方法。空数组转换为空字符串。空字符串转换为数字0。具有单个元素的数组将转换为与一个元素相同的字符串。如果数组包含单个数字,则将该数字转换为字符串,然后返回到数字。

对“为什么”问题的第二种回答,除了“因为规范说”,从设计的角度解释了为什么行为是有意义的。在这个问题上,我只能猜测。首先,如何将数组转换为数字?我能想到的唯一明智的可能性是将一个空数组转换为0,将任何非空数组转换为1,但正如韦恩的回答所揭示的,在许多类型的比较中,一个空数组将被转换为0。除此之外,很难为Array.value eOf()找到一个合理的原始返回值。因此,人们可能会说,这只是更有意义的Array.valueOf()是默认的,并返回Array本身,导致toString()是ToPrimitive使用的结果。将Array转换为字符串而不是数字更有意义。

此外,正如弗拉纳根的引语所暗示的那样,这个设计决策确实允许某些类型的有益行为。例如:

var a = [17], b = 17, c=1;console.log(a==b);      // <= trueconsole.log(a==c);      // <= false

此行为允许您将单个元素数组与数字进行比较,并获得预期的结果。




查看完整回答
反对 回复 2019-07-28
  • 3 回答
  • 0 关注
  • 415 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信