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

來源:互聯網
上載者:User
前言

這個世界總有那麼些人喜歡較真,喜歡研究,這不, 在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.

    附言

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

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

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

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

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

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.