前面已經說到,JS 是一種採用即時編譯(JIT)的語言,雖然過程十分短暫迅速,依然經歷了編譯這個環節。
這裡就來稍微快速理解一下,編譯時具體都做了些什麼。
對機器來說,工程師敲出的原始碼(source code)是無法理解的內容,編譯器需要翻譯這些代碼,轉變成能夠執行的機器語言。
在分詞/詞法分析階段,編譯器會將一行代碼分割成有意義的最小單位,這些代碼塊被稱為「詞法單元(token)」。
如 var a = 2;
會被分成以下幾個詞法單元:var
、a
、=
、2
、;
,每個詞法單元都是個別具有意義的片段。
在解析階段,解析器(Parser)會將詞法單元組成的「詞法單元流(token stream)」轉換成一個由巢狀元素所組成的程序語法結構樹,也就是「抽象語法樹(Abstract Syntax Tree, AST)」。
這階段的主要目的,是把從程序中收集的信息儲存到數據結構中。
詞法分析和解析通常是交錯進行的,每拆解出一個詞法單元,就會交給解析器處理,然後再處理下一個詞法單元。
語義分析是根據語言規則與程式上下文(context)進行語義的檢查與處理。其中一個主要工作是類型檢查,如函數的實參和形參類型是否匹配。
形參:全名為形式參數(formal argument),即是指變數,用來盛裝不特定值的容器。
實參:全名為實際參數(actual argument),即是調用函式時實際傳遞的值。
語意分析只能處理靜態類型的語言,動態類型語言沒有這個步驟。
關於動態語言 v.s. 靜態語言,以及強型別 v.s. 弱型別的比較,可以參考這篇文章。
這個步驟依照每個語言和平台各自有不同處理。如 Google 為 chrome 開發的 V8 引擎,就包含內聯(Inlining)、記憶體管理(Memory management)、垃圾回收(Garbage Collection)等優化行為。
將抽象語法樹(AST)轉換成可執行代碼過程。
= = = = =
除了語義分析以外,JS 基本上經歷過上述每個步驟。比起最初單純的直譯式語言,這些在編譯時提前完成的工作,才能讓 JS 如今才能有極佳的效能活躍於各種平台。