1.1 編譯原理函數
傳統編譯步驟性能
分詞/詞法分析(拆分紅一個個詞法單元)——>解析/語法分析(詞法單元流轉化爲抽象語法樹)——>代碼生成(將抽象語法書(AST)轉化爲可執行代碼(機器指令))優化
js引擎比上述要複雜,在各個階段會有特定步驟來對性能進行優化,好比冗餘元素。spa
其餘不少語言的編譯多發生在構建以前,而js大部分狀況下的編譯是發生在代碼執行前的短短几微秒內,沒有其餘語言編譯器那樣有那麼多的時間進行優化,因此js引擎想了各類辦法來保證性能最佳(好比JIT,能夠延遲編譯甚至實施重編譯)。blog
1.2 理解做用域作用域
以var a = 2爲例,執行這個語句須要引擎,編譯器,做用域的配合。編譯器
編譯器查詢方式io
以LHS和RHS爲例,LHS查詢是視圖找到變量的容器自己,並對去賦值,而RHS是簡單的查找某個變量的值。console
好比console.log(a),這裏對a的引用就是RHS,並無進行任何賦值。編譯
而a=2,這裏對a的引用就是LHS,並不關心當前的值是什麼,只是要爲 '=2' 這個賦值操做找到一個目標。
注:eg:foo(a)中實際上含有一個隱式 'a=2' 操做,不要忽略這一個LHS查詢。
注:函數聲明function foo(a) {...}不能簡單的理解爲LHS查詢和賦值操做(var foo,foo = function(a){...}),由於編譯器能夠在代碼生成的同時處理聲明和值的定義。
1.4 異常
在變量尚未聲明的狀況下,這兩種查詢的行爲是不一樣的。RHS若是找不到該變量,引擎會拋出ReferenceError的錯誤,而LHS則會在全局做用域下建立一個具備該名稱的變量,並將其返還給引擎(須要程序運行在非'嚴格模式'下,'嚴格模式'下,引擎會拋出同RHS相似的ReferenceError異常)。