CodeMash 2012 的“Wat"演讲中提到的这些奇怪的 JavaScript 行为的解释是什么? [英] What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wat' talk for CodeMash 2012?

查看:20
本文介绍了CodeMash 2012 的“Wat"演讲中提到的这些奇怪的 JavaScript 行为的解释是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CodeMash 2012 的Wat"演讲 基本上指出Ruby 和 JavaScript 的一些奇怪的怪癖.

The 'Wat' talk for CodeMash 2012 basically points out a few bizarre quirks with Ruby and JavaScript.

我在 http://jsfiddle.net/fe479/9/.

下面列出了 JavaScript 特有的行为(因为我不知道 Ruby).

The behaviours specific to JavaScript (as I don't know Ruby) are listed below.

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

I found in the JSFiddle that some of my results didn't correspond with those in the video, and I am not sure why. I am, however, curious to know how JavaScript is handling working behind the scenes in each case.

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

我很好奇 + 在 JavaScript 中与数组一起使用时的操作符.这与视频的结果相符.

I am quite curious about the + operator when used with arrays in JavaScript. This matches the video's result.

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

这与视频的结果相符.这里发生了什么?为什么这是一个对象.+ 运算符的作用是什么?

This matches the video's result. What's going on here? Why is this an object. What does the + operator do?

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

这与视频不符.视频显示结果为 0,而我得到 [Object].

This doesn't match the video. The video suggests that the result is 0, whereas I get [Object].

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

这也和视频不符,输出一个变量怎么会导致两个对象?也许我的 JSFiddle 是错误的.

This doesn't match the video either, and how does outputting a variable result in two objects? Maybe my JSFiddle is wrong.

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

执行 wat + 1 导致 wat1wat1wat1wat1...

Doing wat + 1 results in wat1wat1wat1wat1...

我怀疑这只是简单的行为,试图从字符串中减去一个数字会导致 NaN.

I suspect this is just straightforward behaviour that trying to subtract a number from a string results in NaN.

推荐答案

以下是对您所看到(并且应该看到)结果的解释列表.我使用的参考资料来自 ECMA-262 标准.

Here's a list of explanations for the results you're seeing (and supposed to be seeing). The references I'm using are from the ECMA-262 standard.

  1. [] + []

    当使用加法操作符时,左右操作数首先被转换为原语(§11.6.1).根据 §9.1,将对象(在本例中为数组)转换为原语返回其默认值,对于具有有效 toString() 方法的对象,该值是调用 object.toString() 的结果(§8.12.8).对于数组,这与调用 array.join() 相同(§15.4.4.2).加入一个空数组会产生一个空字符串,因此加法运算符的第 7 步返回两个空字符串的连接,即空字符串.

  1. [] + []

    When using the addition operator, both the left and right operands are converted to primitives first (§11.6.1). As per §9.1, converting an object (in this case an array) to a primitive returns its default value, which for objects with a valid toString() method is the result of calling object.toString() (§8.12.8). For arrays this is the same as calling array.join() (§15.4.4.2). Joining an empty array results in an empty string, so step #7 of the addition operator returns the concatenation of two empty strings, which is the empty string.

类似于[] + [],两个操作数都先转换为原语.对于对象对象"(第 15.2 节),这又是调用 object.toString() 的结果,对于非空、非未定义的对象,它是 [object Object]"(§15.2.4.2).

Similar to [] + [], both operands are converted to primitives first. For "Object objects" (§15.2), this is again the result of calling object.toString(), which for non-null, non-undefined objects is "[object Object]" (§15.2.4.2).

这里的 {} 没有被解析为一个对象,而是一个空块 (§12.1,至少只要您不强制该语句成为表达式,但稍后会详细介绍).空块的返回值为空,因此该语句的结果与 +[] 相同.一元 + 运算符(§11.4.6) 返回 ToNumber(ToPrimitive(operand)).正如我们已经知道的,ToPrimitive([]) 是空字符串,根据 §9.3.1ToNumber("") 为 0.

The {} here is not parsed as an object, but instead as an empty block (§12.1, at least as long as you're not forcing that statement to be an expression, but more about that later). The return value of empty blocks is empty, so the result of that statement is the same as +[]. The unary + operator (§11.4.6) returns ToNumber(ToPrimitive(operand)). As we already know, ToPrimitive([]) is the empty string, and according to §9.3.1, ToNumber("") is 0.

与前一种情况类似,第一个 {} 被解析为具有空返回值的块.同样,+{}ToNumber(ToPrimitive({})) 相同,ToPrimitive({})"[object Object]"(见[] + {}).所以为了得到+{}的结果,我们必须在字符串"[object Object]"上应用ToNumber.当按照 §9.3.1 中的步骤进行操作时,我们得到 结果为 NaN:

Similar to the previous case, the first {} is parsed as a block with empty return value. Again, +{} is the same as ToNumber(ToPrimitive({})), and ToPrimitive({}) is "[object Object]" (see [] + {}). So to get the result of +{}, we have to apply ToNumber on the string "[object Object]". When following the steps from §9.3.1, we get NaN as a result:

如果语法不能将 String 解释为 StringNumericLiteral 的扩展,那么 ToNumberNaN.

If the grammar cannot interpret the String as an expansion of StringNumericLiteral, then the result of ToNumber is NaN.

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

    根据 §15.4.1.1§15.4.2.2Array(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).join("wat" - 1)

    As per §15.4.1.1 and §15.4.2.2, Array(16) creates a new array with length 16. To get the value of the argument to join, §11.6.2 steps #5 and #6 show that we have to convert both operands to a number using ToNumber. ToNumber(1) is simply 1 (§9.3), whereas ToNumber("wat") again is NaN as per §9.3.1. Following step 7 of §11.6.2, §11.6.3 dictates that

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

    If either operand is NaN, the result is NaN.

    所以 Array(16).join 的参数是 NaN.按照 §15.4.4.5 (Array.prototype.join),我们必须在参数上调用 ToString,即 "NaN" (§9.8.1):

    So the argument to Array(16).join is NaN. Following §15.4.4.5 (Array.prototype.join), we have to call ToString on the argument, which is "NaN" (§9.8.1):

    如果 mNaN,则返回字符串 "NaN".

    If m is NaN, return the String "NaN".

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

    Following step 10 of §15.4.4.5, we get 15 repetitions of the concatenation of "NaN" and the empty string, which equals the result you're seeing. When using "wat" + 1 instead of "wat" - 1 as argument, the addition operator converts 1 to a string instead of converting "wat" to a number, so it effectively calls Array(16).join("wat1").

    至于为什么您会看到 {} + [] 情况下的不同结果:将其用作函数参数时,您将强制语句成为 ExpressionStatement,这使得无法将 {} 解析为空块,因此将其解析为空对象字面量.

    As to why you're seeing different results for the {} + [] case: When using it as a function argument, you're forcing the statement to be an ExpressionStatement, which makes it impossible to parse {} as empty block, so it's instead parsed as an empty object literal.

    这篇关于CodeMash 2012 的“Wat"演讲中提到的这些奇怪的 JavaScript 行为的解释是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆