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

資訊專欄INFORMATION COLUMN

JavaScript深入之執(zhí)行上下文棧

codecraft / 1468人閱讀

摘要:深入系列第三篇,講解執(zhí)行上下文棧的是如何執(zhí)行的,也回答了第二篇中的略難的思考題。

JavaScript深入系列第三篇,講解執(zhí)行上下文棧的是如何執(zhí)行的,也回答了第二篇中的略難的思考題。

順序執(zhí)行?

如果要問到 JavaScript 代碼執(zhí)行順序的話,想必寫過 JavaScript 的開發(fā)者都會有個直觀的印象,那就是順序執(zhí)行,畢竟:

var foo = function () {

    console.log("foo1");

}

foo();  // foo1

var foo = function () {

    console.log("foo2");

}

foo(); // foo2

然而去看這段代碼:

function foo() {

    console.log("foo1");

}

foo();  // foo2

function foo() {

    console.log("foo2");

}

foo(); // foo2

打印的結(jié)果卻是兩個 foo2。

刷過面試題的都知道這是因為 JavaScript 引擎并非一行一行地分析和執(zhí)行程序,而是一段一段地分析執(zhí)行。當(dāng)執(zhí)行一段代碼的時候,會進行一個“準(zhǔn)備工作”,比如第一個例子中的變量提升,和第二個例子中的函數(shù)提升。

但是本文真正想讓大家思考的是:這個“一段一段”中的“段”究竟是怎么劃分的呢?

到底JavaScript引擎遇到一段怎樣的代碼時才會做“準(zhǔn)備工作”呢?

可執(zhí)行代碼

這就要說到 JavaScript 的可執(zhí)行代碼(executable code)的類型有哪些了?

其實很簡單,就三種,全局代碼、函數(shù)代碼、eval代碼。

舉個例子,當(dāng)執(zhí)行到一個函數(shù)的時候,就會進行準(zhǔn)備工作,這里的“準(zhǔn)備工作”,讓我們用個更專業(yè)一點的說法,就叫做"執(zhí)行上下文(execution contexts)"。

執(zhí)行上下文棧

接下來問題來了,我們寫的函數(shù)多了去了,如何管理創(chuàng)建的那么多執(zhí)行上下文呢?

所以 JavaScript 引擎創(chuàng)建了執(zhí)行上下文棧(Execution context stack,ECS)來管理執(zhí)行上下文

為了模擬執(zhí)行上下文棧的行為,讓我們定義執(zhí)行上下文棧是一個數(shù)組:

    ECStack = [];

試想當(dāng) JavaScript 開始要解釋執(zhí)行代碼的時候,最先遇到的就是全局代碼,所以初始化的時候首先就會向執(zhí)行上下文棧壓入一個全局執(zhí)行上下文,我們用 globalContext 表示它,并且只有當(dāng)整個應(yīng)用程序結(jié)束的時候,ECStack 才會被清空,所以 ECStack 最底部永遠有個 globalContext:

    ECStack = [
        globalContext
    ];

現(xiàn)在 JavaScript 遇到下面的這段代碼了:

function fun3() {
    console.log("fun3")
}

function fun2() {
    fun3();
}

function fun1() {
    fun2();
}

fun1();

當(dāng)執(zhí)行一個函數(shù)的時候,就會創(chuàng)建一個執(zhí)行上下文,并且壓入執(zhí)行上下文棧,當(dāng)函數(shù)執(zhí)行完畢的時候,就會將函數(shù)的執(zhí)行上下文從棧中彈出。知道了這樣的工作原理,讓我們來看看如何處理上面這段代碼:

// 偽代碼

// fun1()
ECStack.push( functionContext);

// fun1中竟然調(diào)用了fun2,還要創(chuàng)建fun2的執(zhí)行上下文
ECStack.push( functionContext);

// 擦,fun2還調(diào)用了fun3!
ECStack.push( functionContext);

// fun3執(zhí)行完畢
ECStack.pop();

// fun2執(zhí)行完畢
ECStack.pop();

// fun1執(zhí)行完畢
ECStack.pop();

// javascript接著執(zhí)行下面的代碼,但是ECStack底層永遠有個globalContext
解答思考題

好啦,現(xiàn)在我們已經(jīng)了解了執(zhí)行上下文棧是如何處理執(zhí)行上下文的,所以讓我們看看上篇文章《JavaScript深入之詞法作用域和動態(tài)作用域》最后的問題:

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();

兩段代碼執(zhí)行的結(jié)果一樣,但是兩段代碼究竟有哪些不同呢?

答案就是執(zhí)行上下文棧的變化不一樣。

讓我們模擬第一段代碼:

ECStack.push( functionContext);
ECStack.push( functionContext);
ECStack.pop();
ECStack.pop();

讓我們模擬第二段代碼:

ECStack.push( functionContext);
ECStack.pop();
ECStack.push( functionContext);
ECStack.pop();

是不是有些不同呢?

當(dāng)然了,這樣概括的回答執(zhí)行上下文棧的變化不同,是不是依然有一種意猶未盡的感覺呢,為了更詳細講解兩個函數(shù)執(zhí)行上的區(qū)別,我們需要探究一下執(zhí)行上下文到底包含了哪些內(nèi)容,所以歡迎閱讀下一篇《JavaScript深入之變量對象》。

下一篇文章

《JavaScript深入之變量對象》

深入系列

JavaScript深入系列目錄地址:https://github.com/mqyqingfeng/Blog。

JavaScript深入系列預(yù)計寫十五篇左右,旨在幫大家捋順JavaScript底層知識,重點講解如原型、作用域、執(zhí)行上下文、變量對象、this、閉包、按值傳遞、call、apply、bind、new、繼承等難點概念。

如果有錯誤或者不嚴(yán)謹?shù)牡胤?,請?wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎star,對作者也是一種鼓勵。

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

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

相關(guān)文章

  • JavaScript深入執(zhí)行下文

    摘要:深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧變量對象作用域鏈?zhǔn)侨绾巫兓?。前言在深入之?zhí)行上下文棧中講到,當(dāng)代碼執(zhí)行一段可執(zhí)行代碼時,會創(chuàng)建對應(yīng)的執(zhí)行上下文。 JavaScript深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的demo為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧、變量對象、作用域鏈?zhǔn)侨绾巫兓摹?前言 在《Jav...

    gougoujiang 評論0 收藏0
  • 【進階1-2期】JavaScript深入執(zhí)行下文和變量對象

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

    Richard_Gao 評論0 收藏0
  • JavaScript深入作用域鏈

    摘要:下面,讓我們以一個函數(shù)的創(chuàng)建和激活兩個時期來講解作用域鏈?zhǔn)侨绾蝿?chuàng)建和變化的。這時候執(zhí)行上下文的作用域鏈,我們命名為至此,作用域鏈創(chuàng)建完畢。 JavaScript深入系列第五篇,講述作用鏈的創(chuàng)建過程,最后結(jié)合著變量對象,執(zhí)行上下文棧,讓我們一起捋一捋函數(shù)創(chuàng)建和執(zhí)行的過程中到底發(fā)生了什么? 前言 在《JavaScript深入之執(zhí)行上下文?!分兄v到,當(dāng)JavaScript代碼執(zhí)行一段可執(zhí)行代...

    waltr 評論0 收藏0
  • JavaScript深入閉包

    摘要:深入系列第八篇,介紹理論上的閉包和實踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。定義對閉包的定義為閉包是指那些能夠訪問自由變量的函數(shù)。 JavaScript深入系列第八篇,介紹理論上的閉包和實踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。 定義 MDN 對閉包的定義為: 閉包是指那些能夠訪問自由變量的函數(shù)。 那什么是自由變量呢? 自由變量是指在函數(shù)中使用的,但既不是函數(shù)參數(shù)也...

    caige 評論0 收藏0
  • 深入學(xué)習(xí)js——執(zhí)行下文

    摘要:當(dāng)遇到函數(shù)調(diào)用時,引擎為該函數(shù)創(chuàng)建一個新的執(zhí)行上下文并把它壓入當(dāng)前執(zhí)行棧的頂部。參考鏈接理解中的執(zhí)行上下文和執(zhí)行棧深入之執(zhí)行上下文棧 開篇 作為一個JavaScript的程序開發(fā)者,如果被問到JavaScript代碼的執(zhí)行順序,你腦海中是不是有一個直觀的印象 -- JavaScript 是順序執(zhí)行的,可事實真的是這樣的嗎? 讓我們首先看兩個小例子: var foo = functio...

    Lucky_Boy 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<