js - 12 JS作用域和作用域鏈

作用域

  • 在一些類似C語(yǔ)言的編程語(yǔ)言中,花括號(hào)內(nèi)的每一段代碼都具有各自的作用域,而且變量在聲明它們的代碼段之外是不可見(jiàn)的,我們稱為塊級(jí)作用域。

  • 而在js中并沒(méi)有塊級(jí)作用域,取而代之的使用了函數(shù)作用域:變量在聲明它們的函數(shù)體以及函數(shù)體嵌套的任意函數(shù)體都是定義的

  • 如下:

function test(o){              
 var i = 0;                      // i在整個(gè)函數(shù)體內(nèi)均是有定義的
 if(typeOf o == "object"){       
   var j = 0;                    // j在函數(shù)體內(nèi)是有定義的,不僅僅在這個(gè)代碼段
   for(var k = 0; k < 10; k ++){  // k在函數(shù)體內(nèi)是有定義的,不僅僅在這個(gè)循環(huán)內(nèi) 
     console.log(k)              // => 1~9     
    };
    consloe.log(k)               // => k已經(jīng)定義,輸出10
  };
  console.log(j)                 // => j已定義,但沒(méi)有初始化
}
  • js的函數(shù)作用域是指在函數(shù)內(nèi)聲明的所有變量在函數(shù)體內(nèi)始終是可見(jiàn)的有意思的是,這就意味著變量在申明之前就甚至已經(jīng)可用(這種特性被非正式的成為“聲明提前”,即javascript引擎的“預(yù)編譯”時(shí)進(jìn)行)
    如:
var scope = "global";
function f(){
   console.log(scope);            // 輸出undefined,而不是“global”
   var scope = "local";          // 變量在這里賦值,在函數(shù)體內(nèi)的任何位置都有定義
   console.log(scope);           // 輸出“l(fā)ocal”
}

以上,雖然在函數(shù)f()外,scope被定義,但執(zhí)行到函數(shù)內(nèi)第一行時(shí)就被重新定義,但未被賦值,所以輸出undefined,運(yùn)行到第二行時(shí)才被賦值。為了方便理解上述函數(shù)f()可以寫(xiě)成

function f(){
   var scope;
   console.log(scope);            
   var scope = "local";          
   console.log(scope);
}

作用域鏈(純理論,理解!理解!理解?。?/h3>
  • javascript是基于詞法作用域的語(yǔ)言,即通過(guò)閱讀包含變量定義在內(nèi)的源碼就能知道變量的作用域
  • 全局變量在程序中始終有定義,局部變量在聲明它的函數(shù)體內(nèi)以及所嵌套的函數(shù)內(nèi)有定義

概念

每一段js代碼都有一個(gè)與之關(guān)聯(lián)的作用域鏈,這個(gè)作用域鏈?zhǔn)且粋€(gè)對(duì)象列表或者鏈表,這組對(duì)象定義了這段代碼“作用域中”的變量,當(dāng)js需要找一個(gè)變量x時(shí),會(huì)從鏈中的第一個(gè)對(duì)象開(kāi)始,沒(méi)有就找下一個(gè),如果在一個(gè)對(duì)象中找到名為x的屬性,就會(huì)停止,如果在鏈中沒(méi)有找到說(shuō)明該鏈中并不存在x,并最終拋出一個(gè)引用錯(cuò)誤(ReferenceError)異常.

  • 在js最頂層的代碼中(也就是不包含在任何函數(shù)定義內(nèi)的代碼),作用域由一個(gè)全局對(duì)象組成。
  • 在不包含嵌套的函數(shù)體內(nèi),作用域鏈上有兩個(gè)對(duì)象:
    1.定義函數(shù)參數(shù)和局部變量的對(duì)象。
    2.全局對(duì)象
  • 在一個(gè)含有嵌套函數(shù)體內(nèi),作用域鏈上至少有三個(gè)對(duì)象

理解

  • 當(dāng)定義一個(gè)函數(shù)時(shí),它實(shí)際上保存一個(gè)作用鏈。調(diào)用這個(gè)函數(shù)時(shí),將創(chuàng)建一個(gè)新的對(duì)象來(lái)儲(chǔ)存它的局部變量,并將這個(gè)對(duì)象添加至保存的那個(gè)作用鏈上,同時(shí)創(chuàng)建一個(gè)新的更長(zhǎng)的表示函數(shù)調(diào)用作用域的”鏈“
  • 對(duì)于嵌套函數(shù)來(lái)講,每次調(diào)用一個(gè)外部函數(shù)時(shí),作用域都是不同的,內(nèi)部函數(shù)又會(huì)重新定義一遍。因?yàn)槊看握{(diào)用外部函數(shù)的時(shí)候,作用域鏈型都是不同的,內(nèi)部函數(shù)在每次調(diào)用的時(shí)候都有微妙的差別(在每次調(diào)用外部函數(shù)時(shí),內(nèi)部函數(shù)的代碼都是相同的,而且關(guān)聯(lián)這段代碼的作用域鏈也不同)。

?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 前言 對(duì)于js中的閉包,無(wú)論是老司機(jī)還是小白,我想,見(jiàn)得不能再多了,然而有時(shí)三言兩語(yǔ)卻很難說(shuō)得明白,反正在我初學(xué)時(shí)...
    itclanCoder閱讀 4,298評(píng)論 1 11
  • 一、作用域 一個(gè)變量的作用域(scope)是程序源代碼中定義的這個(gè)變量的區(qū)域。 在JS中使用的是詞法作用域(lex...
    博聞強(qiáng)記富內(nèi)斯閱讀 903評(píng)論 0 5
  • 作用域與作用域鏈 一、作用域 一個(gè)變量的作用域(scope)是程序源代碼中定義的這個(gè)變量的區(qū)域。 在JS中使用的是...
    e81bcd463937閱讀 608評(píng)論 0 2
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,674評(píng)論 1 32
  • 1體驗(yàn)大于一切 2自身實(shí)力很重要 3堅(jiān)持做自己想做的,對(duì)自己有成長(zhǎng)的事 4做一切事一定要做好最壞的打算 5借力pp...
    包萬(wàn)鴻閱讀 251評(píng)論 0 0

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