函數(shù)作用域

我們先來(lái)了解幾個(gè)概念:
執(zhí)行期上下文:當(dāng)函數(shù)執(zhí)行時(shí)罪帖,會(huì)創(chuàng)建一個(gè)稱為執(zhí)行期上下文的內(nèi)部對(duì)象热监。一個(gè)執(zhí)行期上下文定義了一個(gè)函數(shù)執(zhí)行時(shí)的環(huán)境嚎幸,函數(shù)每次執(zhí)行時(shí)對(duì)應(yīng)的執(zhí)行上下文都是獨(dú)一無(wú)二的揖铜,所以多次調(diào)用一個(gè)函數(shù)會(huì)導(dǎo)致創(chuàng)建多個(gè)執(zhí)行上下文弹灭,當(dāng)函數(shù)執(zhí)行完畢州疾,它所產(chǎn)生的執(zhí)行上下文被銷毀辜限。

  <pre>解析1:執(zhí)行期上下文指的就是函數(shù)執(zhí)行前一刻所產(chǎn)生的AO對(duì)象</pre>
  <pre>解析2:函數(shù)執(zhí)行環(huán)境就是指變量提升函數(shù)提升得到的那些AO對(duì)象屬性</pre>
  <pre>解析3:
  function test() { }

  函數(shù)多次調(diào)用,產(chǎn)生不同的AO對(duì)象:
  test();           ---->AO{}
  test();           ---->AO{}
  函數(shù)執(zhí)行完畢之后對(duì)應(yīng)的AO對(duì)象銷毀严蓖。
  </pre>

[[scope]]:每個(gè)js函數(shù)都是一個(gè)對(duì)象薄嫡,對(duì)象中有些屬性我們可以訪問(wèn),但有些不可以颗胡,這些屬性僅供js引擎存取毫深,[[scope]]就是其中一個(gè)。

  function test() { }

  我們可以訪問(wèn)的函數(shù)屬性(如:test.length/test.prototype);
  我們不能訪問(wèn)但著實(shí)存在的函數(shù)屬性(如:test.[[scope]])

作用域鏈:[[scope]]中所存儲(chǔ)的執(zhí)行期上下文對(duì)象的集合毒姨,這個(gè)集合呈鏈?zhǔn)竭B接哑蔫,我們把這種鏈?zhǔn)竭B接叫做作用域鏈。
結(jié)合著例子來(lái)理解一下:

  function a() {
    function b() {
        var b=234;
    }
  }
  var glob = 100;
  a();

a函數(shù)被定義時(shí)發(fā)生如下過(guò)程:


作用域鏈1.jpg

先不要細(xì)琢磨上面GO里放置的各個(gè)屬性弧呐。上面a.[[scope]]還沒(méi)有構(gòu)成一個(gè)鏈闸迷,只有GO對(duì)象的存在,下面繼續(xù)俘枫。

a函數(shù)被執(zhí)行時(shí)腥沽,發(fā)生如下過(guò)程:


作用域鏈2.jpg

a函數(shù)執(zhí)行前一刻所產(chǎn)生的AO對(duì)象放到了a函數(shù)作用域a.[[scope]]的頂端;現(xiàn)在a.[[scope]]上已構(gòu)成一個(gè)鏈.
查找變量:從作用域鏈的頂端依次向下查找(再補(bǔ)充:在哪個(gè)函數(shù)里查找變量鸠蚪,就去哪個(gè)函數(shù)的作用域頂端去查找)今阳,最標(biāo)準(zhǔn)的說(shuō)法师溅。

再繼續(xù)研究剛剛的例子:

  function a() {
    function b() {
        var b=234;
    }
}
var glob = 100;
a();

b函數(shù)被創(chuàng)建時(shí),發(fā)生如下過(guò)程:


作用域鏈3.jpg

也就是說(shuō)b函數(shù)剛剛出生時(shí)所在的環(huán)境是a執(zhí)行的結(jié)果盾舌,直接給b函數(shù)的出生創(chuàng)造好了環(huán)境墓臭。

b函數(shù)被執(zhí)行時(shí),發(fā)生如下過(guò)程:


作用域鏈4.jpg

b函數(shù)執(zhí)行前一刻產(chǎn)生的AO對(duì)象放置在b.[[scope]]的最頂端⊙矗現(xiàn)在透徹地理解一下窿锉,在函數(shù)b中去訪問(wèn)變量時(shí),是在b函數(shù)的作用域[[scope]]最頂端去查找變量窖维。

再深入剖析看看榆综,檢查自己是否理解清楚了:

首先,a作用域中的頂端AO與b作用域的第二個(gè)AO是同一個(gè)AO的引用么铸史?還是兩個(gè)不同的AO?

答案:是同一個(gè)AO的引用怯伊,下面代碼來(lái)驗(yàn)證一下

    function a() {
        function b() {
        var b=234;
            aa=0;
        }
    var aa=123;
        b( );
        console.log(aa);//輸出0琳轿,代表變量aa在語(yǔ)句b()執(zhí)行完之后,值被改變了耿芹。
}
var glob = 100;
a();

GO{
    glob:100,
    a:~~~~~
}

    AO(a){
        aa:0,
         b:~~~~~~   
    }
         

再來(lái),在上面的例子中,第7行b函數(shù)執(zhí)行完之后移怯,概念上是執(zhí)行期上下文被銷毀邦泄,而實(shí)際函數(shù)a和函數(shù)b的作用域變化應(yīng)該是什么樣的呢?
答案:

  • b函數(shù)執(zhí)行完之后砸彬,自己的執(zhí)行期上下文AO被干掉(銷毀)颠毙,即b.[[scope]]回到b被定義的狀態(tài)。
  • 往下進(jìn)行到第9行砂碉,a函數(shù)執(zhí)行完后蛀蜜,b函數(shù)作用域b.[[scope]]直接被銷毀;同時(shí)增蹭,a函數(shù)的執(zhí)行期上下文AO被銷毀滴某,a.[[scope]]回到被定義的狀態(tài),a函數(shù)等待下一次被調(diào)用執(zhí)行滋迈。
    思考一下霎奢,下面函數(shù)執(zhí)行的作用域鏈:
  function a() {
    function b(){
        function c() {
        
        }
        c();
    }
    b();
}
a();

具體過(guò)程如下

a 定義:  a.[[scope]]    -->   0:GO

a 執(zhí)行:  a.[[scope]]    -->   0:AO(a)
                             1:GO
                             
b 定義:  b.[[scope]]    -->   0:AO(a)
                             1:GO
注意b執(zhí)行了才會(huì)產(chǎn)生c的定義哈!饼灿!
b 執(zhí)行:  b.[[scope]]    -->   0:AO(b)
                             1:AO(a)
                             2:GO
                             
c 定義:  c.[[scope]]    -->   0:AO(b)
                             1:AO(a)
                             2:GO
                             
c 執(zhí)行: c.[[scope]]    -->   0:AO(c)
                             1:AO(b)
                             2:AO(a)
                             3:GO

現(xiàn)在再來(lái)看這句話幕侠,函數(shù)里邊能訪問(wèn)函數(shù)外邊的變量,但函數(shù)外邊不能訪問(wèn)呢函數(shù)里邊的變量赔退;從上邊的過(guò)程來(lái)看橙依,在b中訪問(wèn)c中的局部變量证舟,是不可能的,因?yàn)閎.[[scope]]中不存在函數(shù)c的執(zhí)行期上下文AO(c)窗骑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末女责,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子创译,更是在濱河造成了極大的恐慌抵知,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件软族,死亡現(xiàn)場(chǎng)離奇詭異刷喜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)立砸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門掖疮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人颗祝,你說(shuō)我怎么就攤上這事浊闪。” “怎么了螺戳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵搁宾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我倔幼,道長(zhǎng)盖腿,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任损同,我火速辦了婚禮翩腐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘揖庄。我一直安慰自己栗菜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蹄梢。 她就那樣靜靜地躺著疙筹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪禁炒。 梳的紋絲不亂的頭發(fā)上而咆,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音幕袱,去河邊找鬼暴备。 笑死,一個(gè)胖子當(dāng)著我的面吹牛们豌,可吹牛的內(nèi)容都是我干的涯捻。 我是一名探鬼主播浅妆,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼障癌!你這毒婦竟也來(lái)了凌外?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涛浙,失蹤者是張志新(化名)和其女友劉穎康辑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體轿亮,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疮薇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了我注。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片按咒。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖仓手,靈堂內(nèi)的尸體忽然破棺而出胖齐,到底是詐尸還是另有隱情,我是刑警寧澤嗽冒,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站补履,受9級(jí)特大地震影響添坊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箫锤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一贬蛙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谚攒,春花似錦阳准、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至括儒,卻和暖如春绕沈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帮寻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工乍狐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人固逗。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓浅蚪,卻偏偏與公主長(zhǎng)得像藕帜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惜傲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355