編譯原理
傳統(tǒng)編譯語言
- 詞法分析:將由字符組成的字符串分解成(對編譯語言來說)有意義的代碼塊号杠,這些代碼塊被稱為詞法單元慕趴。
- 解析/語法分析:將詞法單元流(數(shù)組)轉(zhuǎn)換成一個由元素逐級嵌套所組成的代表了程序語法結(jié)構(gòu)的樹酬土,即“抽象語法樹”(abstract syntax tree囚戚,AST)沼填。
- 代碼生成:將AST轉(zhuǎn)換成可執(zhí)行代碼的過程被稱為代碼生成朋其。這個過程與語言倦始、目標平臺等息息相關(guān)斗遏。
相比只有三個步驟的語言的編譯器,javascript引擎要復(fù)雜的多鞋邑。例如诵次,在語法分析和代碼生成階段有特定的步驟來對運行性能進行優(yōu)化,包括對冗余元素進行優(yōu)化枚碗。簡單的說逾一,任何javascript代碼片段在執(zhí)行前都要進行編譯(通常就在執(zhí)行前)
理解作用域
- 程序處理過程中的角色:
1.引擎
從頭到尾負責整個javascript程序的編譯和執(zhí)行過程
2.編譯器
負責語法分析及代碼生成等臟活累活
3.作用域
負責收集并維護由所有聲明的標識符(變量)組成的一系列查詢,并實施一套非常嚴格的規(guī)則肮雨,確定當前執(zhí)行的代碼對這些標識符的訪問權(quán)限遵堵。
簡單的說:作用域是一套規(guī)則,用于確定在何處以及如何查找變量(標識符) - 變量的賦值操作
var a=2;
會執(zhí)行兩個動作怨规,首先編譯器會在當前作用域聲明一個變量(如果之前沒有聲明過)陌宿,然后運行時引擎會在作用域中查找該變量,如果能夠找到就會對他賦值:
1.編譯器在編譯過程的第二步中生成了代碼波丰,引擎執(zhí)行它時壳坪,會通過查找變量來判斷它是否以聲明過,查找的過程由作用域進行協(xié)助掰烟。
2.引擎有兩種查找類型:(1)如果查找的目的是對變量進行賦值弥虐,那么就會使用LHS查詢,(2) 如果目的是獲取變量的值媚赖,就會使用RHS查詢。這兩種查詢都會在當前執(zhí)行作用域中開始珠插,如果他們沒有找到所需的標識符惧磺,就會向上級作用域繼續(xù)查找目標標識符,最后抵達全局作用域捻撑,這時候無論找不找的到都將停止磨隘。
3.不成功的RHS引用會導(dǎo)致拋出ReferenceError異常:在所有嵌套的作用域中遍尋不到所需的變量缤底。不成功的LHS引用會導(dǎo)致自動隱式創(chuàng)建一個全局變量(非嚴格模式下),該變量使用LHS引用的目標作為標識符番捂,或者拋出ReferenceError異常(嚴格模式下)
4.如果RHS查詢找到了一個變量个唧,但你嘗試對這個變量的值進行不合理的操作,比如試圖對一個非函數(shù)類型的值進行函數(shù)調(diào)用设预,或者引用null或undefined類型的值中的屬性徙歼,那么引擎會拋出另外一種類型的異常,叫做TypeError鳖枕。ReferenceError同作用域判別的失敗相關(guān)魄梯,而TypeError則代表作用域判別成功了,但是對結(jié)果的操作是非法或不合理的