JavaScript排版陷阱 – return的分號地雷

印象中,JavaScript跟C、C#一樣,可以在程式碼段落中任意插入空白、換行而維持相同語意,屬於Free-Form Language的一員。

雖然排成這樣沒什麼道理,但以下JavaScript可以執行無誤:

        function calc(a, b) {
            var c = (a
                + b
                ) / 2
            ;
            return c;
        }
        alert(calc(5, 4));

手邊有段程式,在完成初步測試後花了點時間重新檢視程式碼,進行一些調整美化,在某個function中,由於return傳回的字串有點長,為了讓排版更好看一些,我改成以下寫法:

        function getSomething() {
            // ... blah blah ...
            return
            "line1 blah blah blah blah blah" +
            "line2 blah blah blah blah blah" +
            "line3 blah blah blah blah blah";
        }

改完後重新測試程式,晴天霹靂! 原本可以跑的程式壞掉了!!

由於這波程式微調的地方不少,花了好些時間才抓出問題出在原本return "line1 blah..."被改成return接換行,下一行才放"line1 blah..."。

經過研究,得知這個雷人陷阱有個專業術語叫Automatic Semicolon Insertion (ASI),JavaScript引擎會自動在以下指令後方加上分號";": [參考]

  • empty statement
  • var statement
  • expression statement
  • do-while statement
  • continue statement
  • break statement
  • return statement
  • throw statement

ASI跟return結合在一起,最為惡名昭彰、傷人無數... 網路上可以找到很多相關文章。簡單來說,前述的doSomething會程式會被解析成:

        function getSomething() {
            // ... blah blah ...
            return;
            "line1 blah blah blah blah blah" +
            "line2 blah blah blah blah blah" +
            "line3 blah blah blah blah blah";
        }

於是doSomething()傳回undefined,導致不正常的結果。

而ASI的特性,只有JavaScript有,return後方換行再寫,在C#、C、Java上都不會有問題,無怪乎許多程式老鳥也會中箭,在調整JavaScript程式碼排版時,宜多加留意!

歡迎推文分享:
Published 21 September 2012 10:48 PM 由 Jeffrey
Filed under:



意見

# Huang47 said on 22 September, 2012 09:08 PM

建議跑 linter, jslint or jshint

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<September 2012>
SunMonTueWedThuFriSat
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
 
RSS
【工商服務】
OrcsWeb: Windows Server Hosting
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication