作用域鏈與閉包

作用域鏈 Scope Chain

作用域鏈?zhǔn)且粭l變量對象組成的鏈,與執(zhí)行上下文有關(guān),用于處理標(biāo)識符時進(jìn)行變量查詢。
函數(shù)擁有一個內(nèi)部屬性[[scope]],該屬性由ES3規(guī)范定義,只能被JS引擎讀寫。[[scope]]包含一個函數(shù)被創(chuàng)建的作用域中對象的集合,這個集合就是作用域鏈。


靈魂圖例.png

函數(shù)執(zhí)行時,沒遇到一個變量,都會在作用域鏈中進(jìn)行查找。按順序查AO/VO,遍歷對象中的鍵,尋找同名標(biāo)識符。若該變量對象中無同名標(biāo)識符,則查找下一個VO。如果遍歷完作用域鏈還沒找到,則會拋出 * is not defined 的錯誤。

這就是shadow的原因,當(dāng)在不同一個VO中由同名標(biāo)識符時,會取前一個的值,此時后一個就被shadow了。

作用域鏈在代碼執(zhí)行時只會被with及catch改變。

  1. with
    with語句傳入的對象會被插入作用域鏈的首位。
  2. catch
    catch語句會把捕獲到的異常插入作用域鏈的首位。

閉包 closures

定義

有權(quán)訪問另一個函數(shù)作用域中變量的函數(shù)——紅寶書

能夠訪問自由變量(函數(shù)中既非函數(shù)參數(shù)arguments亦非局部變量的變量)的函數(shù)——MDN

當(dāng)閉包被創(chuàng)建時,閉包的[[scope]]屬性被初始化,[[scope]]包含了與執(zhí)行環(huán)境作用域鏈相同的對象的引用。
例如:

    var x = 10;

    function test(){
      console.log(x);
    }

    (()=>{
      var x = 20;
      test();   //10
    })();

因為[[scope]]時創(chuàng)建執(zhí)行上下文時就創(chuàng)建的,作用域鏈時這個時候確定的,是靜態(tài)詞法鏈。

Function構(gòu)造器創(chuàng)建的函數(shù)[[scope]]只包含全局對象

例如:

    var x = 10;
    function test(){
      var y = 20;
      var test1 = Function('console.log(x)');
      var test2 = Function('console.log(y)');
      test1(); //10
      test2(); // Uncaught ReferenceError: y is not defined
    }

    test();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容