你不知道的Javascript(上卷)讀書筆記之一 ---- 做用域

你不知道的Javascript(上卷)這本書在我看來是一本還不錯的書籍,這本書用比較簡潔的語言來描述Js的那些」坑」,在這裏寫一些博客記錄一下筆記以便消化吸取。git

1 編譯原理github

在此書中,開始便提出:Javascript是一門編譯型語言,我一開始覺得這是國內翻譯的鍋,翻譯的不夠準確,後來我還專門去github看了,做者確實是將Js描述爲一門編譯型語言(compiled language)。然而我認爲做者更想表達的是Js也擁有和Java通常的特定的編譯過程.而不是傳統得認爲只是單純的進行」解釋執行」。函數

編譯型語言的定義是編譯型語言的首先將源代碼編譯生成機器語言,再由機器運行機器語言,就如C/C++通常。性能

Java把源代碼編譯成爲JVM能夠執行的字節碼,明顯是不符合編譯型語言的定義的,因此Java是一門解釋型語言。而Javascript也擁有同Java相似的過程,可是這個過程很短。這它在代碼執行前的幾微秒內要完成程序的編譯,而後立刻執行。spa

Javascript的編譯分爲三個步驟:翻譯

a.分詞/詞法分析 對象

b.解析/語法分析 ip

c.代碼生成內存

Javascript在編譯階段的語法分析和代碼生成階段使用了各類方法(JIT, 延遲編譯, 重編譯等)保證性能最佳。作用域

2 理解做用域

書中所說的Javascript的解釋和執行的過程,主要就幾個角色參與:

引擎:負責編譯的第一部分(分詞/詞法分析)和執行編譯後生成的代碼

編譯器:負責編譯的第二部分(語法分析)和編譯的第三部分(代碼生成)

做用域:負責收集全部聲明的標識符,即變量,而且維護一套管理變量的規則
對於var a = 2;能夠認爲他的執行過程以下

a.引擎執行編譯的第一步 分詞/詞法分析

b.引擎調用編譯器,編譯器進行編譯的語法分析和代碼生成

           a) 編譯器遇到var a,去當前的做用域集合中查找是否存在a這個變量

           b) 若是存在,則忽略變量聲明

           c) 若是不存在,則在做用域中聲明一個新的變量,命名爲a

           d) 生成引擎運行所需代碼

c.引擎運行生成的代碼

            a) 去當前做用域中查找是否存在a變量,若是找不到這個變量,它會繼續往上 (它的上一層做用域)尋找

            b) 若是存在,會使用這個變量,併爲這個變量賦值

            c) 若是不存在,會拋出一個異常或者建立一個變量(*詳細請看下文LHS和 RHS)

備註:引擎去做用域查找變量的方式有兩種一種是LHS查詢,另一種是RHS查詢。

a) LHS能夠認爲是表明取得變量的源地址(變量實際上就是計算機內存中一段連續 的地址,而且咱們經過爲變量命名來爲這段內存地址命名),取得源地址用於爲該變量賦值。

b) RHS表明查詢獲得變量的值,通常用於爲其餘變量賦值

直接說LHS和RHS確定太抽象,也很差記,LHS 和 RHS 字面上區別在於 L 和 R,分別表明左(left)和右(right)

對於 a= b = 2 這行代碼,代碼首先爲b賦值爲2。而後呢?重點來了

1首先查詢獲得b的值

2把查詢的獲得的值賦給a

而這,剛好分別對應着RHS查詢和LHS查詢,首先對處於右邊的b進行一次RHS(查詢獲得b的值),而後LHS查詢找到a變量的源地址(爲a賦值)。

函數的執行,好比foo(2),實際是對foo進行一次RHS,獲得的值是函數類型的對象,而後去執行他時,還有一次(多個形參時就是屢次)對形參的LHS

3 做用域嵌套

當一個塊或函數嵌套在另一個塊或函數中時,就發生了做用域的嵌套,所以,若是咱們在一個塊中定義函數的話,函數執行過程當中是能夠調用到函數外層的變量的。

整個的函數做用域鏈就像一個金字塔,在書中做者把函數做用域鏈比喻爲一個建築。在做用域的最頂層是一個全局做用域,每個做用域均可能包含數個子做用域,如此往下延伸,所以金字塔對函數做用域鏈會更貼切。

LHS和RHS都會先在當前做用域進行查找,若是沒有找到結果,那麼它們都會一直往上尋找,直至全局做用域。

4 異常

若是引擎在最頂層的全局做用域中也找不到,那麼會有什麼行爲呢? 在這裏的話,LHS和RHS會有不一樣的行爲

a.對於LHS:若是在最頂層也找不到這個變量,若是在非嚴格模式下,那麼會在全局 做用域建立一個全局變量,若是處於嚴格模式下,嚴格模式禁止自動或隱式建立全 局變量,此時會拋出ReferenceError異常

b.對於RHS:若是在最頂層也找不到這個變量,那麼會拋出ReferenceError異常。若是對查詢的變量進行不合理的操做,好比調用非函數對象,會拋出TypeError異常。

相關文章
相關標籤/搜索