你知道爲啥++[[]][+[]]+[+[]] = 10?

前言

這個世界總有那麼些人喜歡較真,喜歡研究,這不, 在StackOverflow上,有人就很認真的提了這個問題,  幸運的是, 程序員永遠是這個世界上最樂於幫助別人的人羣之一, 於是, 真有人很熱情的blabla的解釋了原因.

想看源地址的可以去這裏: http://stackoverflow.com/questions/7202157/can-you-explain-why-10

問題

++[[]][+[]]+[+[]] 

在js中, 如果我們這樣給一個變量賦值,不難發現它確實能返回一個值,而且還是10, 另外你可以在這裏看到更多更多類似這樣的測試結果.

那麼, 爲什麼會返回值呢?爲什麼又是10呢?

原因

很多熱心人士都給出了自己的解釋, 這裏我就不一一列舉了, 我只翻譯下最佳答案(他解釋得最爲詳細).

  1. 解決問題的最好的方式之一就是分解它, 然後分而治之, 這裏也一樣, 首先上述表達式可以分解爲:
++[[]][+[]] 
+
[+[]]
2. 在js中, 表達式+[]===0的結果爲真, 這其實跟js編譯器的設計有關的, 由於Js是弱類型語言,因此在我們想對某個對象進行一個操作時,js引擎總是會嘗試先將這個對象轉換爲符合指定操作的對象類型然後再執行操作,在這裏+會把後面[]轉換爲0然後執行別的結果,那麼,上面的表達式可以進一步簡化爲下面這樣子:
++[[]][0]
+
[0]
由於[[]][0]表示取得數組[[]]的第一個元素, 因此我們可以得到:
  • [[]][0]返回該數組的內部數組([]),然而, 如果我們直接說[[]][0]===[]卻不對, 爲了避免錯誤的表述, 這裏我們不放先稱這個內部數組爲A.

  • ++[[]][0] == A+1, 因爲在js中,++表示自增1.

  • ++[[]][0] === +(A+1), 或者從另方面說,前面的結果永遠是一個數字(js中,進行+1並不一定能保證結果是數字,但++得到的結果卻永遠是數字)

  3.  讓我們繼續上面的步驟對表達式進一步簡化, 這裏我們把A替換爲[],然後得到簡化的結果:

+([]+1)
+
[0]

 在js中, 後面這個表達式的結果仍然爲真: []+1 ==="1", 因爲空數組轉換爲字符串等同於"", 根據這個特點,我們可以得到下面的結論:

  • +([] +1) === +("" +1);
  • +([] +1) === +("1");
  • +([] +1) === 1.

4. 於是, 表達式可以進一步簡化爲下面這個結果:

  1

  +
[0]

 

 我們不難發現[0] =="0"的結果同樣爲真, 這又是爲啥呢? 其實原因跟上面一樣的, 執行+的操作的時候, js引擎發現[0]是一個包含一個元素0的數組,因此,它會先將這個數組轉換爲字符串, 這樣才能執行+操作(數組能匹配tostring的方法,但默認沒有轉換爲數字的方式), 因此[0]會將其內部的所有元素拼接爲一個字符串"0".

5. 好了, 到了揭曉答案的時刻啦, 通過上面的層層抽絲剝繭, 我們最終發現, 那麼一大堆東西其實最後就是這樣滴(數字+字符串=字符串):


1
+
"0"
=== "10"

Bazinga!!!

關於+[]

問題到這裏結束了麼? 應該沒有,因爲不少同學可能仍然對上面的解釋有些疑問, 那麼下面我們來補充下"+[]"把

首先看看一元操作符"+"的說明:

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()的說明:

Object

Apply the following steps:

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

  2. Return ToString(primValue).

ToPrimitive() 的說明:

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]] 的說明:

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.

關於數組的.toString方法的說明:

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.

根據上面一堆堆的blabla, 我們就可以得出結論啦:+[] 等於+"",因爲 [].join() === "".

 

 這裏, 我們再次回到關於+的定義:

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方法可參照下面的解釋:

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

因此呢, +"" === 0,  從而, +[] ===0.

附言

在這個提供分享和數字化的世界, 我們每天可能看到和學習了很多很多東西, 然後學習是一回事, 真正能學以致用, 將其在工作中融會貫通卻又是另外一回事. 我們學習的最終目的是解決問題和創造新的東西, 但怎麼利用已有的知識去解決問題卻需要我們不斷總結和思考.

因此我這裏翻譯這篇文章也不是僅僅給大家一個樂子, 更期待的是希望你和我能在新的一年中更好的去學會如果利用已知的和已有的資源去解決暫時可能的難題.

因爲工作原因,很久沒寫東西, 在這個歲末旦初的時機終於再次提筆, 雖然只是翻譯, 但也算是對自己有所幫助吧, 希望也能給你帶來一些幫助.

水平有限, 如果有翻譯或者解釋不對的地方,還請大家多多諒解, 有磚請輕拍哈~~

最後, 也祝願園友元旦快樂,年終獎多多把!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章