Javascript明显的疯狂

650*_*502 8 javascript language-design

可能重复:
空JavaScript阵列的冲突布尔值

这个事实背后的理由是什么?

[ ([] == false), ([] ? 1 : 2) ]
Run Code Online (Sandbox Code Playgroud)

回来了[true, 1]?

换句话说,空列表在布尔上下文中逻辑上为真,但等于false.

我知道使用===解决了这个问题,但这个显然完全不合逻辑的选择背后的解释是什么?

换句话说,这被认为是语言中的一个错误,一些无意识的事情刚刚发生并且无法修复,因为它太晚或者真的在语言设计中有人认为这种明显的疯狂是我很酷的我是对许多程序员来说肯定很混乱?

对于如何发生这种情况的技术解释同时令人惊讶和惊吓,但我对这种设计背后的内容更感兴趣.

编辑

我接受了非常详细的Nick Retallack解释,即使它只是关于为什么[]==false是真的技术原因:令人惊讶的是它发生的原因是因为[]转换为字符串是一个空字符串而空字符串数值是特殊的来自0而不是显然更符合逻辑NaN.例如,对于空对象,比较({}) == false返回false,因为空对象的字符串表示形式不是空字符串.

我的好奇心仍然是所有这一切都是出乎意料的(现在不幸在标准中固化).

Phi*_*ton 9

这里的混淆是围绕JavaScript中"falsy"的定义,(与普遍看法相反)并不相同== false.

Falsy实际上是指一个布尔值等于false的值,而不是一个结果为== false的表达式.在JavaScript中唯一Falsy值是:false,0,"",null,undefined,和NaN.因此,任何这些值 - 或任何评估其中一个值的表达式(如在if声明中或使用三元运算符)都是假的.

这是我在JavaScript中汇总了falsy/truthy值的表格,它可以帮助解释整个问题. http://jsfiddle.net/philipwalton/QjSYG/

  • 真棒小提琴. (5认同)

Nic*_*ack 8

让我们获得技术支持.我将用ECMAScript标准262中的引用来解释逻辑.

表达[] ? 1 : 2很简单:

11.12条件运算符(?:)

  • 让lref成为评估LogicalORExpression的结果.
  • 如果ToBoolean(GetValue(lref))为真,那么
    • 设trueRef是评估第一个AssignmentExpression的结果.
    • 返回GetValue(trueRef).
  • 其他
    • 设falseRef是评估第二个AssignmentExpression的结果.
    • 返回GetValue(falseRef)

9.2 ToBoolean

  • 未定义:false
  • 空:虚假
  • Boolean:结果等于输入参数(无转换).
  • Number:如果参数为+ 0,0或NaN,则结果为false; 否则结果是真的.
  • String:如果参数为空String(其长度为零),则结果为false; 否则结果是真的.
  • 对象:true

这是真的.


现在,对于使用双等于运算符时发生的事情的狂野之旅.也许这有助于解释为什么你永远不应该这样做.

==的行为在第11.9.3节:抽象等式比较算法中进行了解释.

对于x == y,其中x = []且y = false,会发生以下情况:

11.9.3:抽象等式比较算法

如果Type(y)是布尔值,则返回比较结果x == ToNumber(y)

9.3 ToNumber

如果参数为false,则 结果为+0.

现在我们有[] == 0

11.9.3:抽象等式比较算法

如果Type(x)是Object而Type(y)是String或Number,则返回比较结果ToPrimitive(x)== y.

9.1 ToPrimitive

返回Object的默认值.通过调用对象的[[DefaultValue]] 内部方法,传递可选提示PreferredType 来检索对象的默认值.对于8.12.8中的所有本机ECMAScript对象,此规范定义了[[DefaultValue]]内部方法的行为.

8.12.8 DefaultValue:

当没有提示调用O的[[DefaultValue]]内部方法时,它的行为就像提示是数字一样

  • 设valueOf是使用参数"valueOf"调用对象O的[[Get]]内部方法的结果.
  • 如果IsCallable(valueOf)为真,那么,
    • 设val是调用valueOf的[[Call]]内部方法的结果,其中O为此值和空参数列表.
    • 如果val是原始值,则返回val
  • 设toString是使用参数"toString"调用对象O的[[Get]]内部方法的结果.
  • 如果IsCallable(toString)为真,那么,
    • 令str为调用toString的[[Call]]内部方法的结果,其中O为此值,且为空参数列表.
    • 如果str是原始值,则返回str.

我假设这首先尝试valueOf然后拒绝它,因为结果是你开始使用的相同数组.然后它调用Array上的toString,它似乎普遍实现为以逗号分隔的值列表.对于像这样的空数组,这会导致空字符串.

现在我们有'== 0

11.9.3:抽象等式比较算法

如果Type(x)是String而Type(y)是Number,则返回比较结果ToNumber(x)== y

9.3.1 ToNumber应用于字符串类型

StringNumericLiteral为空或仅包含空格将转换为+0.

现在我们有0 == 0

11.9.3:抽象等式比较算法

如果x与y的Number值相同,则返回true

真棒.这是真的.虽然这里有相当复杂的方式.