成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

什么是JavaScript的作用域

開發 前端
現代編程語言的最基本功能之一就是能夠存儲變量當中的值,以便于之后的使用于修改。也正是這個功能將狀態帶給了程序。在JavaScript中,作用域就是一套設計良好的規則來存儲變量。

 作用域的概念

現代編程語言的最基本功能之一就是能夠存儲變量當中的值,以便于之后的使用于修改。也正是這個功能將狀態帶給了程序。

在JavaScript中,作用域就是一套設計良好的規則來存儲變量。

簡述編譯原理

通常我們會將JavaScript歸類為“動態”或“解釋執行“語言,但它實際上是一門編譯語言。與傳統的編譯語言不同,它不是提前編譯的,編譯結果也不能在分布式系統中進行移植。

例如V8引擎,為了提高JavaScript代碼的運行性能,在運行之前會先將其編譯為本地的機器碼,然后再去執行機器碼,達到提升速度的目的。

  •  分詞/詞法分析

           這個過程將由字符組成的代碼分解成對程序有意義的代碼塊,這些代碼塊被稱為詞法單元。

    例如 var foo = 'bar' 通常會被分解為這些詞法單元:var 、 foo 、 = 、 'bar'

  •  解析/語法分析

           這個過程將詞法單元轉換成一個“由元素逐級嵌套組成的代表程序語法的樹“,這個樹被稱為“抽象語法樹”(AST)。    

    image

  •  代碼生成

          將上邊的抽象語法樹轉換為機器可執行代碼

JavaScript引擎比只有三個步驟的語言的編譯器要復雜的多。例如在語法分析和代碼生成階段有特定的步驟來對運行性能進行優化,包括對冗余元素進行優化等。

對于JavaScript來說,大部分情況下編譯發生在代碼執行的前幾微秒,任何代碼片段在執行前都要進行編譯。因此JavaScript編譯器首先對 var foo = 'bar' 進行編譯,然后做好執行它的準備,并且通常馬上就會執行它。

引擎、編譯器、作用域在賦值操作中的配合

  •  引擎:從頭到尾負責整個JavaScript程序編譯及執行過程
  •  編譯器:負責語法分析及代碼生成
  •  作用域:負責收集維護由所有變量組成的一系列查詢

對于 var foo = 'bar' 這段代碼,大家很有可能認為是一句簡單的聲明。而事實上JavaScript執行時會將它分成兩個完全不同的聲明。

  1.  編譯器首先將這段代碼分解成詞法單元,然后解析為樹結構。(在下一步代碼生成時,處理這段代碼的方式會跟預期有所不同)
  2.  遇到 var foo ,編譯器會檢查作用域是否已有同名變量存在。如果有的話編譯器會忽略聲明,繼續編譯。否則它會生成代碼在當前作用域的變量集合中聲明一個新的變量,命名為 foo
  3.  接下來編譯器會為引擎生成運行時所需代碼,用來處理 foo = 'bar' 這個賦值操作。
  4.  引擎運行時會首先查詢當前作用域是否存在叫做 foo 的變量。如果有引擎則會使用這個變量,否則會一直向上層作用域查找。
  5.  如果最終找到了 foo 這個變量,就會將 'bar' 賦給它,否則拋出異常。

總結:變量的賦值會執行兩個動作:首先是編譯器在當前作用域中聲明變量(如果變量未被聲明過);接著運行時引擎在作用域查找該變量,能找到就會對它賦值。

LHS查詢 vs RHS查詢

引擎執行編譯器生成的代碼時,會通過查找 foo 來判斷是否已經聲明過。查找的過程由作用域來協助。在我們的例子中,引擎為變量 foo 進行的時LHS查詢,還有另一個查找類型叫RHS查詢。顧名思義,它們的意思是Left hand side 和 Right hand side

  •  LHS:變量出現在賦值操作的左側(查找賦值操作的目標是誰)
  •  RHS:變量在其他位置出現(查找值的源頭) 
  1. // 考慮下邊的代碼  
  2. console.log(foo) 

此例中 foo 的引用就是RHS查詢,這里沒有賦予 foo 任何值,相反的,我們需要查找 foo 的值,才能傳遞給log方法。 

  1. // 相比之下  
  2. foo = 'bar' 

這里對 foo 的查詢則是LHS查詢,我們并不關心 foo 當前的值是什么, 只是想為這個賦值操作找到目標。 

  1. // 再分析下邊的代碼  
  2. function foo(a) {  
  3.   console.log(a)  
  4.  
  5. foo('bar') 

這段代碼里既有LHS查詢又有RHS查詢

  1.  最后一行 foo(...) 函數的調用需要對 foo 進行RHS查詢 → 找到 foo 的值
  2.  入參時存在隱式的 a = 'bar' ,需要對 a 進行LHS查詢
  3.  console.log(a) 對 a 進行RHS查詢
  4.  console.log(...) 本身也需要對 console 對象進行RHS查詢

作用域的嵌套

我們在文章開始時說過,作用域是根據名稱查找變量的一套規則。實際情況中需要同時顧及幾個作用域。

當一個塊或函數嵌套在另一個塊或函數中時,就發生了作用域的嵌套。因此在當前作用域中沒有查找到目標變量時,會逐層向上查找直到全局作用域。 

  1. // 考慮以下代碼  
  2. function foo(a) { 
  3.  console.log(a + b)  
  4.  
  5. var b = 258 
  6. foo(369) 

對 b 進行的RHS查詢無法在 foo 內部完成,但可以在上一級的作用域中完成(在此例中是全局作用域)。

LHS,RHS查詢都會在作用域內逐層查找,直到找到為止(或到達全局作用域)。

ReferenceError

上一節提到了LHS,RHS都會在作用域內逐層查找變量,但如果到達全局作用域仍然沒有找到變量怎么辦呢?

這時區分LHS和RHS查詢的意義就體現出來了。

如果RHS查詢在所有嵌套的作用域中都沒有找到所需變量,引擎就會拋出 ReferenceError。

如果LHS查詢在所有嵌套的作用域中都沒有找到所需變量,引擎就會在全局作用域中創建一個具有該名稱的變量,并將其返回給引擎。

注意:ES5中引入了嚴格模式,與普通模式相比,嚴格模式其中一個不同就是進制自動或隱式的創建全局變量。因此在嚴格模式下LHS查詢失敗時不會創建并返回全局變量,引擎同樣會拋出 ReferenceError。

總結

  •  作用域是一套規則,用于確定在何處以及如何查找變量。如果查找的目的是對變量賦值,會使用LHS查詢;如果目的是獲取變量的值,會使用RHS查詢。
  •  JavaScript引擎會在代碼執行前對其進行編譯。在這個過程中,像 var foo = 'bar' 這種聲明會被分解成兩個獨立的步驟。

            1.  var foo 在其作用域中聲明新的變量。此操作在代碼執行前進行。

            2.  接下來 foo = 'bar' 會查詢(LHS)變量 foo 并對其賦值。

  •  LHS和RHS查詢都會在當前執行作用域中開始,如果有需要(沒有在當前作用域找到變量)就會向上級作用域繼續查找目標變量,一直抵達全局作用域,無論找到與否都會停止。
  •  不成功的RHS查找會導致拋出 ReferenceError ,不成功的LHS查找會導致自動隱式地創建一個全局變量(非嚴格模式下),或者拋出 ReferenceError(嚴格模式下)。 

 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2011-09-06 09:56:24

JavaScript

2019-03-13 08:00:00

JavaScript作用域前端

2011-04-18 09:31:35

JavaScript

2013-09-05 10:07:34

javaScript變量

2017-09-14 13:55:57

JavaScript

2011-05-12 18:26:08

Javascript作用域

2015-07-21 13:39:58

Javascript作用域

2016-12-19 11:10:32

JavaScript變量作用域

2021-12-06 07:15:48

Javascript作用域閉包

2015-07-03 11:23:51

JavaScript作用域聲明提前

2021-07-01 11:56:51

JavaScript開發代碼

2020-12-16 11:09:27

JavaScript語言開發

2015-10-20 13:11:23

JavascriptHoisting

2021-11-28 15:15:13

軟件測試域測試開發

2010-09-29 15:02:23

DHCP作用域

2021-05-25 10:15:20

JavaScript 前端作用域

2009-03-16 09:39:01

函數詞法作用域Javascript

2021-03-17 08:39:24

作用域作用域鏈JavaScript

2021-03-09 08:35:51

JSS作用域前端

2021-03-16 22:25:06

作用域鏈作用域JavaScript
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产sm主人调教女m视频 | 国产精品日韩欧美一区二区三区 | 91免费电影| 亚洲永久字幕 | 色婷婷一区二区三区四区 | 日韩中文字幕一区二区 | 狠狠色网 | 久久精品亚洲国产奇米99 | 亚av在线 | 久久久久九九九女人毛片 | 天天精品综合 | 精品毛片视频 | 精品中文字幕久久 | 亚洲午夜精品一区二区三区 | 久久99久久 | 精品欧美一区二区久久久伦 | 精品国产亚洲一区二区三区大结局 | 中文字幕在线观看一区二区 | 成人免费在线视频 | 青青草一区 | 狠狠操在线 | 国产免费一区二区三区免费视频 | 午夜影院在线观看免费 | 国产成人精品免费视频大全最热 | 亚洲精品视频一区 | 超碰精品在线观看 | 91精品国产91久久久久久三级 | 999久久久国产精品 欧美成人h版在线观看 | 综合第一页 | 亚洲天堂一区 | 久草视频在线播放 | 久久69精品久久久久久久电影好 | 天天操网| 精品视频一区二区 | 亚洲精品一区二区在线观看 | 欧美电影在线观看网站 | 欧美精品日韩精品 | 天天色天天射天天干 | 亚洲精品视频在线播放 | 日韩1区| 精品国产欧美一区二区 |