你不知道的JavaScript(上)1

利用空餘時間讀完這三本小黃書,順手寫寫筆記與感想,必定有很大的收穫。

第一章 做用域是什麼?

還沒讀幾行,一個觀點狠狠的衝擊着個人認知。java

儘管一般將JavaScript歸類爲「動態」或「解釋執行」語言,但事實上它是一門編譯語言。編程

???

我尋思着JS不是解釋性語言嗎?緩緩打出三問號,繼續捋。bash

編譯語言VS解釋性語言(我的理解)

  • 編譯語言:編譯器先將編程語言轉換成中間文件(如java的.class的文件),再將它轉換成機器語言。
  • 解釋性語言:直接將變成語言轉換成機器語言,可是依賴解釋器。解釋一行,執行一行。

我仍是沒搞明白編程語言

因而我參考到了這篇文章: baijiahao.baidu.com/s?id=159152…ide

可是,我仍是偏向解釋性語言...函數

關於文章裏面的知識點,咱慢慢捋。ui

編譯語言中,一段源代碼在執行前到底經歷了什麼?

  • 分詞/詞法分析

var a = 'trio'; 分解成 var、a、=、'trio'、;spa

  • 語法分析

將上一步的成果詞法單元轉換成一顆抽象語法樹(AST)code

  • 代碼生成

將AST轉換成機器能識別的代碼對象

複雜嗎?書中指出JavaScript引擎要比那些編譯過程只有三個步驟的語言的編譯器,要複雜的多。

對於JavaScript來講,大多數編譯發生在代碼執行前的那一刻!而參與JavaScript工做的有三個重量嘉賓:

  • 引擎

從頭至尾負責整個程序的編譯及執行

  • 編譯器

語法分析、代碼生成

  • 做用域

負責收集並維護由全部聲明的標識符組成的一系列查詢

模擬一下

var a = 2; 
// 咱們都知道 上述代碼至關於 
var a; // ①
a = 2; // ②
複製代碼

引擎也是這麼認爲的

其中①是編譯器在編譯時乾的活,②是引擎本身的工做。

編譯器會向做用域肯定受否有這個變量,是否須要再次聲明。而引擎則會執行賦值操做。

深層次解釋變量提高

JS引擎在代碼執行的前一刻會對其進行編譯(好比 var a = 2; var a 部分直接交給了編譯器),而編譯器會告訴做用域,去幫我建立一個a變量,可是沒有值。因此編譯的過程,也就是變量提高的過程。

LHS和LRS

number = 1; // ①
console.log(number); // ②
複製代碼

這兩行代碼,引擎都須要去問做用域查詢number這個變量是否存在以及是否有值。可是咱們細品一下,他們之間有所不一樣。

①要找到number這個變量,根本不在意你有沒有值,我在意的是你這個玩意兒有沒有。(LHS)

②要找number這個變量,我要不折不扣的取到你這個值,傳入個人log函數。(RHS)

考慮如下代碼
function foo(a){
    console.log(a)
}
foo(2)
複製代碼

執行foo的時候,對foo進行RHS。隱式的a=2,對a進行LHS。對a進行RHS,傳入log函數。那console.log是個啥玩意兒?引擎又須要對console這個對象進行RHS。

以前讀過這部分,因此接受的很快。作個題。
function foo(a){
    var b = a;
    return a + b;
}
var c = foo(2)
複製代碼

執行var c = foo(2),對c的LHS查詢,對foo的RHS查詢。傳入參數2,對a的LHS查詢,執行 b = a,對b的LHS查詢,對a的RHS查詢,return a + b ,對a、b分別RHS。

區分LHS和RHS的必要性

a = 1;  //不報錯(非嚴格模式) LHS查詢
複製代碼
console.log(a)  // ReferenceError    a is not defined  RHS查詢
複製代碼

咱們能夠看出:

  • 若是RHS查詢在全部嵌套的做用域中都沒有答案,直接報錯。
  • 若是LHS查詢在全局做用域中也沒法找到目標變量,則全局做用域就會友好的爲引擎建立一個。

這也能夠從更深的角度出發解釋爲何都是對變量的查詢,一個報錯,一個不報錯。

第一章End

相關文章
相關標籤/搜索