javascript 範圍鏈

來源:互聯網
上載者:User

javascript 範圍鏈
執行環境(Execution Context)   所有的javascript代碼都是在一個執行環境中被執行的。它只是一種機制,用來完成運行時範圍、生存期等方面的處理。   代碼分為三種類型:   Global Code   Eval Code  Function Code   這是一個EC結構   可以理解如下:  

activeExecutionContext = {    VO: {...}, // or AO    this: thisValue,    Scope: [ // Scope chain      // 所有變數對象的列表      // for identifiers lookup    ]};

 

   當一段程式開始時,會先進入到全域執行內容環境。此時如果調用了某些函數,就會進入他們的上下文環境,執行完之後再退出該上下文環境。 假設啟用了一個EC1的上下文,圖解如下     變數對象(VO)和使用中的物件(AO)   變數對象是一個與上下文相關的資料範圍,用於儲存被定義在上下文中的變數和函式宣告(不包括函數運算式)。在global全域上下文中,變數對象即使全域對象自身。 copy一個例子  
var foo = 10;function bar() {} // // 函式宣告(function baz() {}); // 函數運算式console.log(  this.foo == foo, // true  window.bar == bar // true);console.log(baz); // 引用錯誤,baz沒有被定義

 

全域上下文中的變數對象(VO)會有如下屬性:   在一個函數的上下文中,變數對象被表示為使用中的物件 使用中的物件在進入上下文中初始化成了 AO = {  arguments: <ArgO>};arguments屬性值就是Arguments對象 之後就是儲存當前內容相關的變數與函式宣告   範圍鏈   範圍鏈是一個 對象列表,用於檢索上下文中出現的 標識符(變數名稱、函式宣告,普通參數)。   在函數建立的時候,當前的範圍鏈被儲存到了函數的[[scope]]屬性中。當進入上下文建立AO/VO之後,上下文(EC)的Scope屬性作了如下處理: Scope = AO|VO + [[Scope]]    知識點就是這些,現在我們來一段代碼,把過程給串聯起來。在這之前,我們要知道另一個知識,就是執行內容的代碼被分成兩個基本的階段來處理 進入執行內容執行代碼 
var x = 10;function foo(m) {  var y = 20;  function bar() {    var z = 30;    alert(x +  y + z + m);  }  bar();}foo(10); // 60

 

首先先進入全域上下文環境   全域內容相關的變數對象(代碼執行時,x才被賦值)是: globalContext.VO === Global = {  x: 10  foo: <reference to function>};globalContext.Scope = globalContext.VO; 當"foo"建立時,  
foo.[[Scope]] = [  globalContext.Scope];//也就是foo.[[Scope]] = [  globalContext.VO];

 

在"foo"啟用時,進入了foo的上下文,foo上下文中的使用中的物件(代碼執行時,y才被賦值)是: fooContext.AO = { arguments:<Arg>, m: 10, y: 20,  bar: <reference to function>};此時foo上下文中的範圍鏈為: fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.: fooContext.Scope = [  fooContext.AO,  globalContext.VO];函數"bar"建立時,其[[scope]]為: bar.[[Scope]] = fooContext.Scope;//也就是bar.[[Scope]] = [  fooContext.AO,  globalContext.VO];同理,bar就不寫了。最後bar內容相關的範圍鏈為:  
barContext.Scope = barContext.AO + bar.[[Scope]] barContext.Scope = [  barContext.AO,  fooContext.AO,  globalContext.VO];

 

在alert執行時,範圍鏈中尋找標示符如下 尋找 x,  barContext.AO 無 ----> fooContext.AO 無 ---->globalContext.VO 有 尋找 Z,  barContext.AO 有 其他的就自己看了。   局部變數、全域變數   在範圍鏈中尋找標識符是需要花時間的,所以就明白為什麼需要盡量使用局部變數(將頻繁使用的全域變數緩衝下來),全域變數盡量少用了。並且with會破壞範圍鏈,它會將指定的VO/AO加入到範圍鏈的頂端,這樣在標識符尋找時,需要尋找更長的範圍鏈。   閉包   理解了上面的概念,閉包就很容易理解了。閉包是代碼塊和建立該代碼塊的上下文中資料的結合。  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.