js的作用域以及作用域鏈

1. JavaScript作用域

1.1 全局作用域

在代碼中任何地方都能訪問到的對(duì)象擁有全局作用域,一般來說以下幾種情形擁有全局作用域:
a) 最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域
b) 所有未定義直接賦值的變量自動(dòng)聲明為擁有全局作用域,如:

function test(){
  a = 3;  // a 具有全局作用域
  var b = 4;
}
test(); 
console.log(a);  //3
console.log(b);  //Uncaught ReferenceError: b is not defined

c) 所有window對(duì)象的屬性擁有全局作用域

1.2 局部作用域

局部作用域一般只在固定的代碼片段內(nèi)可訪問到,最常見的如函數(shù)內(nèi)部。

2. JavaScript作用域鏈

????每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境(execution context),當(dāng)執(zhí)行流進(jìn)入一個(gè)環(huán)境時(shí),函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中,在函數(shù)執(zhí)行之后,棧將其環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。
????當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈(scope chain)。作用域鏈的用途,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。作用域鏈的前端,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象。如果這個(gè)環(huán)境是函數(shù),則將其活動(dòng)對(duì)象(activation object)作為變量對(duì)象?;顒?dòng)對(duì)象在最開始時(shí)只包含一個(gè)變量,即 arguments 對(duì)象(這個(gè)對(duì)象在全局環(huán)境中是不存在的)。作用域鏈中的下一個(gè)變量對(duì)象來自包含(外部)環(huán)境,而再下一個(gè)變量對(duì)象則來自下一個(gè)包含環(huán)境。這樣,一直延續(xù)到全局執(zhí)行環(huán)境;全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象。
????標(biāo)識(shí)符解析是沿著作用域鏈一級(jí)一級(jí)地搜索標(biāo)識(shí)符的過程。搜索過程始終從作用域鏈的前端開始,然后逐級(jí)地向后回溯,直至找到標(biāo)識(shí)符為止(如果找不到標(biāo)識(shí)符,通常會(huì)導(dǎo)致錯(cuò)誤發(fā)生)。
示例:

var a = 1
function fn1(){
  function fn3(){
    function fn2(){
      console.log(a)
    }
    fn2()
    var a = 4
  }
  var a = 2
  return fn3
}
var fn = fn1()
fn()

上述代碼中,最終執(zhí)行的是fn2,但是fn2中并沒有定義變量a,則從其上層作用域也就是fn3去尋找變量a的聲明,由于變量的聲明前置,但是賦值不會(huì)前置,可以在fn3中找到其局部變量a的聲明,但是未被賦值所以值為undefined,所以在執(zhí)行fn2時(shí)會(huì)輸出結(jié)果undefined。

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

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

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