js編譯機制
? ? 首先骚秦,對javascript我們通常稱之為“動態(tài)”或“解釋執(zhí)行語言”她倘,但事實上它是一門編譯語言。但與傳統(tǒng)的編譯語言不同作箍,它不是提前編譯的硬梁,編譯結(jié)果也不能在分布式系統(tǒng)中進行移植。
? ? 在傳統(tǒng)編譯語言的流程中胞得,程序中的一段源代碼在執(zhí)行之前會經(jīng)歷三個步驟荧止,統(tǒng)稱為“編譯”
? ? 1、分詞/詞法分析(Tokenizing/Lexing)
? ? ? ? 這個過程會將由字符組成的字符串分解成(對編程語言來說)有意義的代碼塊阶剑,這些代碼塊被稱為詞法單元(token)跃巡。例如,考慮程序var a = 2; 這段程序通常會被分解成下面這些詞法單元:? var牧愁、a素邪、=、2猪半、兔朦;. 空格是否會被當作詞法單元偷线,取決于空格在這門語言中是否具有意義。
? ? ? ?分詞(tokenizing)和詞法分析(Lexing)之間的區(qū)別是非常微妙的烘绽、晦澀的,主要差異在于詞法單元的識別是通過有狀態(tài)還是無狀態(tài)的方式進行的俐填。簡單來說安接,如果詞法單元生成器在判斷a是一個獨立的詞法單元還是其它詞法單元的一部分時,調(diào)用的是有狀態(tài)的解析規(guī)則英融,那么這個過程就被稱為詞法分析盏檐。
? ? 2、解析/語法分析(Parsing)
? ? ? ? 這個過程是將詞法單元流(數(shù)組)轉(zhuǎn)換成一個由元素逐級嵌套所組成的代表了程序語法結(jié)構(gòu)的樹驶悟。這個樹被稱為“抽象語法樹”(Abstract SyntaxTree, AST)胡野。var a = 2;的抽象語法樹中可能會有一個叫做VariableDeclaration的頂級節(jié)點痕鳍,接下來是一個叫作Identifier(它的值是a)的子節(jié)點硫豆,以及一個叫作AssignmentExpression的子節(jié)點。AssignmentExpression節(jié)點有一個叫作NumericLiteral(它的值是2)的子節(jié)點笼呆。
? ? 3熊响、代碼生成
? ? ? ? 將AST轉(zhuǎn)換成可執(zhí)行代碼的過程被稱為代碼生成。這個過程與語言诗赌、目標平臺等息息相關(guān)汗茄。
? ? ? ? 拋開具體細節(jié),簡單來說就是有某種方法可以將var a = 2;的AST轉(zhuǎn)換為一組機器指令铭若,用來創(chuàng)建一個叫作a的變量(包括分配內(nèi)存等)洪碳,并將一個值儲存在a中。
? ? ? ??
? ? ? ? 任何javascript代碼片段在執(zhí)行前都要執(zhí)行編譯(通常就在執(zhí)行前)叼屠,大部分情況下編譯發(fā)生在代碼執(zhí)行前的幾微秒(甚至更短)的時間內(nèi)瞳腌。比如編譯器對var a= 2;這段代碼進行編譯,然后做好執(zhí)行它的準備镜雨,并且通常馬上就會執(zhí)行它纯趋。
? ? ? ? 最后,對于JS執(zhí)行時關(guān)于分號的問題: J中會自動清除句子和句子之間的空格及tab縮進冷离,這樣就可以允許用戶編寫的代碼更加隨性和更加可讀吵冒,在該行代碼解析的時候如果該行代碼可以解析,就會在該行代碼最后自動填寫分號西剥,如果該行代碼無法解析就會把該行代碼和下一句代碼合并痹栖,直到代碼可以解析。
? ? ? ? JS中如果一個語句以( [ / + - 開頭瞭空, 就有可能于上一句合在一起解析揪阿。