SOFTELメモ Developer's blog

会社概要 ブログ 調査依頼 採用情報 ...
技術者募集中

++[[]][+[]]+[+[]] は “10”

問題

++[[]][+[]]+[+[]] は 10 になる。 なんで!???

確認: ← クリックすると alert(++[[]][+[]]+[+[]]) します。

答え

以下、過程(細かいところは下に補足説明)。

  ++[[]][+[]]+[+[]]
= ++[[]][+[]]  +  [+[]]
= ++[[]][+""]  +  [+""]
= ++[[]][0]  +  [0]
= +([] + 1)  +  [0]
= +("" + 1)  +  [0]
= +("1")  +  [0]
= 1  +  [0]
= 1  +  "0"
= "10"

補足

JavaScriptでは、+[] === 0 である。+ 演算子は対象を数値に変換する。+[] === +”” === 0 となる。

[[]] は、空の配列1個([])の配列([[]])である。[[]][0]は配列の最初の要素を取得するので、[]になる。

++[[]][0] が1になるのは、var a = []; ++a; で、a が1になるのと同じ。

++は1加算するので、++[[]][0] == 「(中の空の配列 + 1)を数字にしたもの」 == 「(”” + 1)を数字にしたもの」 == 「”1″ を数字にしたもの」 == 1。

Javascriptでは、空の配列 [] + 1 == “” + 1 == “1” となる。このときの [] は 空の要素を結合した “” になる。

同様に、1 + [0] の [0] は、要素を結合した文字 “0” になる。

最後に number + string = string のように扱われるので、 1 + “0” === “10” 。

+[] の詳細

This is quite a maze, but to do +[], first it is being converted to a string because that’s what + says:

11.4.6 Unary + Operator

The unary + operator converts its operand to Number type.

The production UnaryExpression : + UnaryExpression is evaluated as follows:

1. Let expr be the result of evaluating UnaryExpression.
2. Return ToNumber(GetValue(expr)).

ToNumber() says:

Object

Apply the following steps:

1. Let primValue be ToPrimitive(input argument, hint String).
2. Return ToString(primValue).

ToPrimitive() says:

Object

Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.

[[DefaultValue]] says:

8.12.8 [[DefaultValue]] (hint)

When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:

1. Let toString be the result of calling the [[Get]] internal method of object O with argument “toString”.
2.If IsCallable(toString) is true then,
a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
b. If str is a primitive value, return str.

The .toString of an array says:

15.4.4.2 Array.prototype.toString ( )

When the toString method is called, the following steps are taken:

1. Let array be the result of calling ToObject on the this value.
2. Let func be the result of calling the [[Get]] internal method of array with argument “join”.
3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.

So +[] comes down to +””, because [].join() === “”.

Again, the + is defined as:

11.4.6 Unary + Operator

The unary + operator converts its operand to Number type.

The production UnaryExpression : + UnaryExpression is evaluated as follows:

1. Let expr be the result of evaluating UnaryExpression.
2. Return ToNumber(GetValue(expr)).

ToNumber is defined for “” as:

The MV of StringNumericLiteral ::: [empty] is 0.

So +”” === 0, and thus +[] === 0.

参考

http://stackoverflow.com/questions/7202157/can-you-explain-why-10

http://sla.ckers.org/forum/read.php?24,33349,33405

関連するメモ

コメント