成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

大話(huà)javascript 2期:執(zhí)行上下文與執(zhí)行上下文棧

denson / 1528人閱讀

摘要:在中,通過(guò)棧的存取方式來(lái)管理執(zhí)行上下文,我們可稱(chēng)其為執(zhí)行棧,或函數(shù)調(diào)用棧。因?yàn)閳?zhí)行中最先進(jìn)入全局環(huán)境,所以處于棧底的永遠(yuǎn)是全局環(huán)境的執(zhí)行上下文。

一、什么是執(zhí)行上下文?
執(zhí)行上下文(Execution Context): 函數(shù)執(zhí)行前進(jìn)行的準(zhǔn)備工作(也稱(chēng)執(zhí)行上下文環(huán)境)

JavaScript在執(zhí)行一個(gè)“代碼段”之前,即解析(預(yù)處理)階段,會(huì)先進(jìn)行一些“準(zhǔn)備工作”,例如掃描JS中var定義的變量、函數(shù)名等,進(jìn)而生成執(zhí)行上下文。

name -
變量對(duì)象(VO, variable object) 當(dāng)前函數(shù)定義的變量、函數(shù)、參數(shù)
作用域鏈(Scope chain) 源代碼定義時(shí)形成的作用域鏈
this

JS中的“代碼段”分為三種:全局代碼段、函數(shù)體代碼段、eval代碼段。(注:ES6之前,JS不存在“代碼塊”作用域的概念,即除了函數(shù)之外所有“{}”里的代碼,都屬于全局作用域)

全局代碼段“準(zhǔn)備工作”包括:

1.變量、函數(shù)表達(dá)式 —— 變量聲明,默認(rèn)賦值為undefined;
2.this —— 賦值;
3.函數(shù)聲明 —— 賦值。

函數(shù)體代碼段“準(zhǔn)備工作”包括:

1.變量、函數(shù)表達(dá)式 —— 變量聲明,默認(rèn)賦值為undefined;
2.this —— 賦值;
3.函數(shù)聲明 —— 賦值;
4.參數(shù) —— 賦值;
5.argument —— 賦值;
6.自由變量的取值作用域 —— 賦值。

evel()不推薦使用,所以不再分析evel代碼段。

至此,“執(zhí)行上下文”的定義可以通俗化為 —— 在執(zhí)行代碼段之前(預(yù)處理階段),把將要用到的所有變量都事先拿出來(lái),有的直接賦值,有的先用undefined占個(gè)空,這些變量共同組成的詞法環(huán)境,即為執(zhí)行上下文環(huán)境。

二、執(zhí)行上下文棧

javaScript是單線(xiàn)程語(yǔ)言,簡(jiǎn)單理解下單線(xiàn)程,就是同個(gè)時(shí)間段只能做一件任務(wù),完成之后才可以繼續(xù)下一個(gè)任務(wù)。
函數(shù)編程中,代碼中會(huì)聲明多個(gè)函數(shù),對(duì)應(yīng)的執(zhí)行上下文也會(huì)存在多個(gè)。在JavaScript中,通過(guò)棧的存取方式來(lái)管理執(zhí)行上下文,我們可稱(chēng)其為執(zhí)行棧,或函數(shù)調(diào)用棧(Call Stack)。

1.棧數(shù)據(jù)結(jié)構(gòu)

要簡(jiǎn)單理解棧的存取方式,我們可以通過(guò)類(lèi)比乒乓球盒子來(lái)分析。如下圖左側(cè)。

棧遵循"先進(jìn)后出,后進(jìn)先出"的規(guī)則,或稱(chēng)LIFO ("Last In First Out") 規(guī)則。

如圖所示,我們只能從棧頂取出或放入乒乓球,最先放進(jìn)盒子的總是最后才能取出。
棧中"放入/取出",也可稱(chēng)為"入棧/出棧"。

總結(jié)棧數(shù)據(jù)結(jié)構(gòu)的特點(diǎn):

后進(jìn)先出,先進(jìn)后出

出口在頂部,且僅有一個(gè)

2.執(zhí)行上下文棧ECS(Execution Context Stack)(函數(shù)調(diào)用棧)
程序執(zhí)行進(jìn)入一個(gè)執(zhí)行環(huán)境時(shí),它的執(zhí)行上下文就會(huì)被創(chuàng)建,并被推入執(zhí)行棧中(入棧);
程序執(zhí)行完成時(shí),它的執(zhí)行上下文就會(huì)被銷(xiāo)毀,并從棧頂被推出(出棧),控制權(quán)交由下一個(gè)執(zhí)行上下文。

因?yàn)镴S執(zhí)行中最先進(jìn)入全局環(huán)境,所以處于"棧底的永遠(yuǎn)是全局環(huán)境的執(zhí)行上下文"。而處于"棧頂?shù)氖钱?dāng)前正在執(zhí)行函數(shù)的執(zhí)行上下文",當(dāng)函數(shù)調(diào)用完成后,它就會(huì)從棧頂被推出(理想的情況下,閉包會(huì)阻止該操作,閉包后續(xù)文章深入詳解)。

"全局環(huán)境只有一個(gè),對(duì)應(yīng)的全局執(zhí)行上下文也只有一個(gè),只有當(dāng)頁(yè)面被關(guān)閉之后它才會(huì)從執(zhí)行棧中被推出,否則一直存在于棧底"

function foo () {
    function bar () {
        return "I am bar";
    }
    return bar();
}
foo();

3.執(zhí)行上下文的生命周期

執(zhí)行上下文的生命周期有兩個(gè)階段:

創(chuàng)建階段(進(jìn)入執(zhí)行上下文)

執(zhí)行階段(代碼執(zhí)行)

創(chuàng)建階段:函數(shù)被調(diào)用時(shí),進(jìn)入函數(shù)環(huán)境,為其創(chuàng)建一個(gè)執(zhí)行上下文,此時(shí)進(jìn)入創(chuàng)建階段
執(zhí)行階段:執(zhí)行函數(shù)中代碼時(shí),此時(shí)執(zhí)行上下文進(jìn)入執(zhí)行階段

創(chuàng)建階段的操作

創(chuàng)建變量對(duì)象

函數(shù)環(huán)境會(huì)初始化創(chuàng)建Arguments對(duì)象(并賦值)

函數(shù)聲明(并賦值)

變量聲明,函數(shù)表達(dá)式聲明(未賦值)

確定this指向(this由調(diào)用者確定)

確定作用域(詞法環(huán)境決定,哪里聲明定義,就在哪里確定)

執(zhí)行階段的操作

變量對(duì)象賦值

變量賦值

函數(shù)表達(dá)式賦值

2.調(diào)用函數(shù)
3.順序執(zhí)行其它代碼

變量對(duì)象和活動(dòng)對(duì)象的區(qū)別:

當(dāng)進(jìn)入到一個(gè)執(zhí)行上下文后,這個(gè)變量對(duì)象才會(huì)被激活,所以叫活動(dòng)對(duì)象(AO),這時(shí)候活動(dòng)對(duì)象上的各種屬性才能被訪(fǎng)問(wèn)。

"創(chuàng)建階段對(duì)函數(shù)聲明做賦值,變量及函數(shù)表達(dá)式僅做聲明,真正的賦值操作要等到執(zhí)行上下文代碼執(zhí)行階段"。

代碼例子1:變量提升

function foo() {
  console.log(a);         // 輸出undefined
  var a = "I am here";    // 賦值
}
foo();

// 實(shí)際執(zhí)行過(guò)程

function foo() {
  var a;                // 變量聲明,var初始化undefined
  console.log(a); 
  a = "I am here";     // 變量重新賦值
}

代碼例子2:函數(shù)聲明優(yōu)先級(jí)

function foo() {
    console.log(bar);
    var bar = 20;
    function bar() {
      return 10;
    }
    var bar = function() {
        return 30;
    }
}
foo();  // 輸出bar()整個(gè)函數(shù)聲明
函數(shù)聲明,變量聲明,函數(shù)表達(dá)式的優(yōu)先級(jí)

函數(shù)聲明,如果有同名屬性,會(huì)替換掉

變量,函數(shù)表達(dá)式

函數(shù)聲明優(yōu)先 > 變量,函數(shù)表達(dá)式

4.執(zhí)行上下文的數(shù)量限制(堆棧溢出)
執(zhí)行上下文可存在多個(gè),雖然沒(méi)有明確的數(shù)量限制,但如果超出棧分配的空間,會(huì)造成堆棧溢出。常見(jiàn)于遞歸調(diào)用,沒(méi)有終止條件造成死循環(huán)的場(chǎng)景。
// 遞歸調(diào)用自身
function foo() {
  foo();
}
foo();

// 報(bào)錯(cuò): Uncaught RangeError: Maximum call stack size exceeded

三、執(zhí)行上下文流程圖

如果你覺(jué)得這篇文章對(duì)你有所幫助,那就順便點(diǎn)個(gè)贊吧,點(diǎn)點(diǎn)關(guān)注不迷路~

黑芝麻哇,白芝麻發(fā),黑芝麻白芝麻哇發(fā)哈!

前端哇發(fā)哈

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101802.html

相關(guān)文章

  • 大話(huà)javascript 4:事件循環(huán)(3)

    摘要:令人困惑的是,文檔中稱(chēng),指定的回調(diào)函數(shù),總是排在前面。另外,由于指定的回調(diào)函數(shù)是在本次事件循環(huán)觸發(fā),而指定的是在下次事件循環(huán)觸發(fā),所以很顯然,前者總是比后者發(fā)生得早,而且執(zhí)行效率也高因?yàn)椴挥脵z查任務(wù)隊(duì)列。 一、定時(shí)器 除了放置異步任務(wù)的事件,任務(wù)隊(duì)列還可以放置定時(shí)事件,即指定某些代碼在多少時(shí)間之后執(zhí)行。這叫做定時(shí)器(timer)功能,也就是定時(shí)執(zhí)行的代碼。 定時(shí)器功能主要由setTim...

    liujs 評(píng)論0 收藏0
  • 大話(huà)javascript 4:事件循環(huán)(2

    摘要:只要指定過(guò)回調(diào)函數(shù),這些事件發(fā)生時(shí)就會(huì)進(jìn)入任務(wù)隊(duì)列,等待主線(xiàn)程讀取。三主線(xiàn)程從任務(wù)隊(duì)列中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱(chēng)為事件循環(huán)。 一、任務(wù)隊(duì)列 同步任務(wù)與異步任務(wù)的由來(lái) 單線(xiàn)程就意味著,所有任務(wù)需要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。如果前一個(gè)任務(wù)耗時(shí)很長(zhǎng),后一個(gè)任務(wù)就不得不一直等著。 如果排隊(duì)是因?yàn)橛?jì)算量大,CPU忙不過(guò)來(lái),倒也算了,但是很多時(shí)候C...

    李昌杰 評(píng)論0 收藏0
  • 大話(huà)javascript 6:this深度解析

    摘要:在這次執(zhí)行期間,函數(shù)中的將指向。在剛剛的例子中,因?yàn)樵谡{(diào)用構(gòu)造函數(shù)的過(guò)程中,手動(dòng)的設(shè)置了返回對(duì)象,與綁定的默認(rèn)對(duì)象被丟棄了。在上面的例子中,一個(gè)賦值給了的函數(shù)稱(chēng)為匿名函數(shù),返回了另一個(gè)箭頭函數(shù)稱(chēng)為匿名函數(shù)。 一、引言 在執(zhí)行上下文的創(chuàng)建階段,會(huì)分別生成變量對(duì)象,建立作用域鏈,確定this指向。this的指向,是在函數(shù)被調(diào)用的時(shí)候確定的。也就是執(zhí)行上下文被創(chuàng)建時(shí)確定的。因此,一個(gè)函數(shù)中的...

    lsxiao 評(píng)論0 收藏0
  • 【進(jìn)階1-2JavaScript深入之執(zhí)行下文和變量對(duì)象

    摘要:本計(jì)劃一共期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)劃,點(diǎn)擊查看前端進(jìn)階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對(duì)象,由于微信不能訪(fǎng)問(wèn)外鏈,點(diǎn)擊閱讀原文就可以啦。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第二天。 本計(jì)劃一共28期,每期...

    Richard_Gao 評(píng)論0 收藏0
  • 【進(jìn)階1-1】理解JavaScript 中的執(zhí)行下文執(zhí)行

    摘要:首次運(yùn)行代碼時(shí),會(huì)創(chuàng)建一個(gè)全局執(zhí)行上下文并到當(dāng)前的執(zhí)行棧中。執(zhí)行上下文的創(chuàng)建執(zhí)行上下文分兩個(gè)階段創(chuàng)建創(chuàng)建階段執(zhí)行階段創(chuàng)建階段確定的值,也被稱(chēng)為。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,,今天是第一天 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)...

    import. 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<