一尘不染

在CodeMash 2012的“ Wat”演讲中提到的这些怪异JavaScript行为的解释是什么?

javascript

下面列出了特定于JavaScript的行为(因为我不了解Ruby)。

我在JSFiddle中发现我的某些结果与视频中的结果不符,我不确定为什么。但是,我很想知道JavaScript在每种情况下如何处理幕后工作。

Empty Array + Empty Array
[] + []
result:
<Empty String>

+当与JavaScript中的数组一起使用时,我对运算符非常好奇。这与视频结果匹配。

Empty Array + Object
[] + {}
result:
[Object]

这与视频结果匹配。这里发生了什么?为什么这是一个对象。什么是+运营商吗?

Object + Empty Array
{} + []
result
[Object]

这与视频不匹配。视频表明结果为0,而我得到了[Object]。

Object + Object
{} + {}
result:
[Object][Object]

这也不匹配视频,输出变量如何导致两个对象?也许我的JSFiddle是错的。

Array(16).join("wat" - 1)
result:
NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN

做wat + 1会导致wat1wat1wat1wat1

我怀疑这是直接的行为,即试图从字符串中减去数字会导致NaN。


阅读 377

收藏
2020-04-23

共1个答案

一尘不染

以下是对您所看到的结果的解释列表。我使用的参考资料来自ECMA-262标准。

  1. [] + []

使用加法运算符时,左操作数和右操作数都首先转换为基元(第11.6.1节)。按照§9.1的规定,将对象(在这种情况下为数组)转换为基元将返回其默认值,对于具有有效toString()方法的对象,这是调用的结果object.toString()(第8.12.8节)。对于数组,这与调用array.join()(§15.4.4.2)相同。连接一个空数组会导致一个空字符串,因此加法运算符的第7步将返回两个空字符串的串联,即空字符串。

  1. [] + {}

与相似[] + [],两个操作数都首先转换为基元。对于“对象对象”(第15.2节),这再次是调用的结果object.toString(),对于非空,非未定义的对象,调用是"[object Object]"(第15.2.4.2节)。

  1. {} + []

{}这里不会被解析为一个对象,而是作为一个空块(§12.1,至少只要你不逼这种说法是一种表达,但稍后详细说明)。空块的返回值为空,因此该语句的结果与相同+[]。一元运算+符(第[11.4.6节)返回ToNumber(ToPrimitive(operand))。众所周知,ToPrimitive([])是空字符串,根据9.3.1节,ToNumber("")为0。

  1. {} + {}

与前一种情况类似,第一种情况{}被解析为具有空返回值的块。同样,+{}和相同ToNumber(ToPrimitive({})),并且ToPrimitive({})"[objectObject]"(请参阅[] + {})。因此,要获得结果+{},我们必须ToNumber在字符串上应用"[object Object]"。按照[§9.3.1的步骤进行[操作时,NaN结果是:

如果语法无法将String解释为 StringNumericLiteral 的扩展,则ToNumber的结果为 NaN

  1. Array(16).join("wat" - 1)

根据§15.4.1.1和§15.4.2.2,Array(16)创建一个长度为16的新数组。要获取要连接的参数的值,§11.6.2步骤#5和#6显示我们必须将两个操作数都转换为a。使用编号ToNumberToNumber(1)仅仅是1第9.3节],而ToNumber("wat")再次NaN按§9.3.1。下面的步骤7§11.6.2,[§11.6.3]决定了

如果任一操作数为 NaN ,则结果为 NaN

因此,的论据Array(16).joinNaN。在§15.4.4.5(Array.prototype.join)之后,我们必须调用ToString参数"NaN"§9.8.1):

如果 mNaN ,则返回String "NaN"

在§15.4.4.5的步骤10之后,我们得到了15个重复的串联连接"NaN"和空字符串,这等于您看到的结果。当使用"wat" + 1代替"wat" - 1作为参数时,加法运算符将转换1为字符串而不是"wat"数字,因此它有效地调用Array(16).join("wat1")

关于为什么看到这种{} + []情况的不同结果:当将其用作函数参数时,您将强制该语句为 ExpressionStatement
,这使得无法将其解析{}为空块,因此将其解析为空对象文字。

2020-04-23