CodeMash 2012 的“Wat”演讲基本上指出了Ruby 和 JavaScript 的一些奇怪的怪癖。
我在http://jsfiddle.net/fe479/9/上做了一个 JSFiddle的结果。
下面列出了特定于 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…
wat1wat1wat1wat1
我怀疑这只是尝试从字符串中减去数字导致 NaN 的简单行为。
这是您所看到(并且应该看到)结果的解释列表。我使用的参考来自ECMA-262 标准。
[] + []
使用加法运算符时,左右操作数都先转换为基元(搂11.6.1)。根据拥抱9.1,将对象(在本例中为数组)转换为原语会返回其默认值,对于具有有效toString()方法的对象,该值是调用的结果object.toString()(拥抱8.12.8)。对于数组,这与调用array.join()(拥抱15.4.4.2 ) 相同。连接一个空数组会产生一个空字符串,所以加法运算符的第 7 步返回两个空字符串的连接,也就是空字符串。
toString()
object.toString()
array.join()
[] + {}
与 类似[] + [],两个操作数都首先转换为基元。对于“对象对象”(搂15.2),这又是调用的结果object.toString(),对于非空、非未定义的对象是"[object Object]"(搂15.2.4.2)。
"[object Object]"
{} + []
这里{}不被解析为一个对象,而是一个空块(拥抱12.1,至少只要你不强迫该语句成为一个表达式,但稍后会详细介绍)。空块的返回值为空,因此该语句的结果与+[]. 一元运算+符 (搂11.4.6 ) 返回ToNumber(ToPrimitive(operand))。正如我们已经知道的那样,ToPrimitive([])是空字符串,根据搂9.3.1,ToNumber("")是 0。
{}
+[]
ToNumber(ToPrimitive(operand))
ToPrimitive([])
ToNumber("")
{} + {}
与前一种情况类似,第一种{}被解析为返回值为空的块。同样,+{}与 相同ToNumber(ToPrimitive({})),并且ToPrimitive({})是"[object Object]"(参见[] + {})。所以要得到 的结果+{},我们必须ToNumber在字符串上应用"[object Object]"。当按照搂9.3.1中的步骤进行操作时,我们得到NaN:
+{}
ToNumber(ToPrimitive({}))
ToPrimitive({})
ToNumber
NaN
如果语法无法将 String 解释为 StringNumericLiteral的扩展,则 ToNumber的结果为 NaN 。
Array(16).join("wat" - 1)
根据搂15.4.1.1和搂15.4.2.2创建Array(16)一个长度为16 的新数组。要获得要加入的参数的值,搂11.6.2步骤#5 和#6 表明我们必须将两个操作数转换为号码使用ToNumber。ToNumber(1)只是 1 (搂9.3 ),而ToNumber("wat")再次是NaN按搂9.3.1。在拥抱 11.6.2的步骤 7 之后,拥抱 11.6.3规定
Array(16)
ToNumber(1)
ToNumber("wat")
如果任一操作数为 NaN ,则结果为 NaN 。
所以 的论点Array(16).join是NaN。继搂15.4.4.5( Array.prototype.join)之后,我们要调用ToString论据,即"NaN"(搂9.8.1 ):
Array(16).join
Array.prototype.join
ToString
"NaN"
如果 m 是 NaN ,则返回 String "NaN" 。
在搂15.4.4.5的第10 步之后,我们得到15 次重复的连接"NaN"和空字符串,这等于您看到的结果。当使用"wat" + 1而不是"wat" -1作为参数时,加法运算符转换1为字符串而不是转换"wat"为数字,因此它有效地调用Array(16).join("wat1").
"wat" + 1
"wat" -1
1
"wat"
Array(16).join("wat1")
至于为什么您会看到不同的{} + []案例结果:当将其用作函数参数时,您将语句强制为 ExpressionStatement ,这使得无法解析{}为空块,因此将其解析为空对象文字。