亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JS 環(huán)境執(zhí)行棧、變量對象、執(zhí)行上下文

enrecul101 / 436人閱讀

摘要:檢查上下文中的參數(shù),建立該對象下的屬性與屬性值檢查當前上下文的函數(shù)聲明,也就是使用關(guān)鍵字聲明的函數(shù)。

    function test() {
        console.log(a);                // undefined
        console.log(foo());            // 2
        
        var a = 1;
        function foo() {
            return 2;
        };
    };
    test();

不是很準確的草圖,大概了解就好。

首先JS解釋器(引擎)開始解釋代碼,構(gòu)建執(zhí)行環(huán)境棧(Execution Context Stack),并根據(jù)執(zhí)行環(huán)境的不同生成不同的執(zhí)行上下文(Execution Context)

棧底永遠是全局上下文(后面說),當遇到test(),確認調(diào)用函數(shù),就創(chuàng)建生成test函數(shù)自己的上下文,然后將函數(shù)執(zhí)行上下文入棧(push on)到執(zhí)行環(huán)境棧中。

testEC(test Execution Context)將會開始創(chuàng)建變量對象,我們知道,當調(diào)用一個函數(shù)(激活),一個新的執(zhí)行上下文就會被創(chuàng)建。而一個執(zhí)行上下文的生命周期可以分為兩個階段。

創(chuàng)建階段:
在這個階段中,執(zhí)行上下文分別會創(chuàng)建變量對象、建立作用域鏈,以及確定this的指向。

代碼執(zhí)行階段:
創(chuàng)建完成后,就會開始執(zhí)行代碼,這個時候,會完成變量賦值,函數(shù)引用,以及執(zhí)行其他代碼。

所以testEC將會生成一個變量對象,與之還有作用域鏈、this(這里先不討論),注意,這里是變量對象的創(chuàng)建階段,用VO簡示。

變量對象的創(chuàng)建,經(jīng)歷以下過程。

建立arguments對象。檢查上下文中的參數(shù),建立該對象下的屬性與屬性值(key-value)

檢查當前上下文的函數(shù)聲明,也就是使用function關(guān)鍵字聲明的函數(shù)。在變量對象中以函數(shù)名建立一個屬性,屬性值為指向該函數(shù)所在內(nèi)存地址的引用。如果函數(shù)名的屬性已經(jīng)存在,那么該屬性將會被新的引用所覆蓋。

檢查當前上下文中的變量聲明,每找到一個變量聲明,就在變量對象中以變量名建立一個屬性,屬性值為undefined。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為undefined,則會直接跳過,原屬性值不會被修改。

所以,于是就有了圖中的VO引用的對象的圖示,這就是變量提升的真正原因,對于函數(shù)聲明,它的優(yōu)先級是大于變量聲明的,所以在創(chuàng)建階段,函數(shù)聲明的函數(shù)名就持有了函數(shù)的引用。而變量賦值需要在后面的執(zhí)行階段才被賦值。

未進入執(zhí)行階段前,變量對象中的屬性都不能被訪問!但是進入執(zhí)行階段之后,變量對象轉(zhuǎn)變?yōu)榱嘶顒訉ο螅ˋctive Object),里面的屬性都能被訪問了,然后開始進行執(zhí)行階段的操作。

進入執(zhí)行階段,這時可稱之為活動對象了(Active Object),將進行賦值操作。于是這時的變量就能被自由訪問了。

關(guān)于arguments對象,是個類數(shù)組結(jié)構(gòu)

目前我的測試:

函數(shù)內(nèi)設(shè)有形參,但是不傳實參,遍歷arguments對象時沒有任何值

函數(shù)內(nèi)不設(shè)形參,但是傳實參,遍歷arguments對象有值對應(yīng)的索引

    function test(a,b,c,d) {
        for (var i in arguments) {
            console.log(i);
        }
        console.log(arguments.length+"個");
    };
    test(1,2,3,4);
    // 0 1 2 3
    // "4個"
    function test2(a,b,c,d) {
        for (var i in arguments) {
            document.write(i+"
") } document.write(arguments.length+"個"); }; test2(); // 什么也沒有 // 0個

腦子里有這副圖后,我們在來看另一個栗子:

      function test() {
        console.log(foo());
        console.log(bar);
        
        var foo = "Hello";
        console.log(foo);
        var bar = function () {
            return "world";
        };
        function foo() {
            return "hello";
        };
    };
    test();
    // "hello"
    // "undefined"
    // "Hello"

主要討論同變量聲明與同變量聲明與函數(shù)聲明的情況,這也是變量對象在創(chuàng)建時所做的工作;

檢查當前上下文的函數(shù)聲明,也就是使用function關(guān)鍵字聲明的函數(shù)。在變量對象中以函數(shù)名建立一個屬性,屬性值為指向該函數(shù)所在內(nèi)存地址的引用。如果函數(shù)名的屬性已經(jīng)存在,那么該屬性將會被新的引用所覆蓋。

檢查當前上下文中的變量聲明,每找到一個變量聲明,就在變量對象中以變量名建立一個屬性,屬性值為undefined。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為undefined,則會直接跳過,原屬性值不會被修改。

如代碼中的foo,在test函數(shù)的執(zhí)行上下文創(chuàng)建變量對象后,創(chuàng)建階段,foo就是變量對象中的的鍵名(Key),而鍵值就是函數(shù)的地址指針,因為函數(shù)聲明的優(yōu)先級大于變量聲明,所以foo此時就持有了函數(shù)的引用,而var foo的變量聲明就被跳過。

執(zhí)行階段,進行賦值操作,foo被重新賦值"Hello",同時變量bar從未賦值(undefined)到持有一個函數(shù)的引用,這就是變量對象=>活動對象,執(zhí)行棧,執(zhí)行上下文所發(fā)生的操作。

關(guān)于全局上下文
    var globla = 10;
    function test() {
        return globla++;
    };
    test();
// 以瀏覽器中為例,全局對象為window
// 全局上下文
windowEC = {
    VO: window,
    scopeChain: {},
    this: window
}

以瀏覽器中為例,全局對象為window。
全局上下文有一個特殊的地方,它的變量對象,就是window對象。而這個特殊,在this指向上也同樣適用,this也是指向window。
除此之外,全局上下文的生命周期,與程序的生命周期一致,只要程序運行不結(jié)束,比如關(guān)掉瀏覽器窗口,全局上下文就會一直存在。其他所有的上下文環(huán)境,都能直接訪問全局上下文的屬性。

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

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

相關(guān)文章

  • 33 個 js 核心概念(一):函數(shù)調(diào)用執(zhí)行下文變量對象

    摘要:最先執(zhí)行完畢的一定是最里面的函數(shù),執(zhí)行過后彈出調(diào)用棧,接著執(zhí)行上一層函數(shù),直至所有函數(shù)執(zhí)行完,調(diào)用棧清空。到這里你應(yīng)該就會明白,上面函數(shù)調(diào)用棧,就是生成了一個函數(shù)的執(zhí)行上下文。 showImg(http://upload-images.jianshu.io/upload_images/7803415-36e8e7d048f63524.jpg?imageMogr2/auto-orient...

    ZHAO_ 評論0 收藏0
  • 一、 函數(shù)調(diào)用執(zhí)行下文變量對象

    摘要:最先執(zhí)行完畢的一定是最里面的函數(shù),執(zhí)行過后彈出調(diào)用棧,接著執(zhí)行上一層函數(shù),直至所有函數(shù)執(zhí)行完,調(diào)用棧清空。到這里你應(yīng)該就會明白,上面函數(shù)調(diào)用棧,就是生成了一個函數(shù)的執(zhí)行上下文。 showImg(http://upload-images.jianshu.io/upload_images/7803415-36e8e7d048f63524.jpg?imageMogr2/auto-orient...

    kbyyd24 評論0 收藏0
  • 一、 函數(shù)調(diào)用,執(zhí)行下文變量對象

    摘要:最先執(zhí)行完畢的一定是最里面的函數(shù),執(zhí)行過后彈出調(diào)用棧,接著執(zhí)行上一層函數(shù),直至所有函數(shù)執(zhí)行完,調(diào)用棧清空。到這里你應(yīng)該就會明白,上面函數(shù)調(diào)用棧,就是生成了一個函數(shù)的執(zhí)行上下文。 showImg(http://upload-images.jianshu.io/upload_images/7803415-36e8e7d048f63524.jpg?imageMogr2/auto-orient...

    BaronZhang 評論0 收藏0
  • 前端進擊的巨人(一):執(zhí)行下文執(zhí)行變量對象

    摘要:在中,通過棧的存取方式來管理執(zhí)行上下文,我們可稱其為執(zhí)行棧,或函數(shù)調(diào)用棧。而處于棧頂?shù)氖钱斍罢趫?zhí)行函數(shù)的執(zhí)行上下文,當函數(shù)調(diào)用完成后,它就會從棧頂被推出理想的情況下,閉包會阻止該操作,閉包后續(xù)文章深入詳解。 寫在開篇 已經(jīng)不敢自稱前端小白,曾經(jīng)吹過的牛逼總要一點點去實現(xiàn)。 正如前領(lǐng)導(dǎo)說的,自己喝酒吹過的牛皮,跪著都得含著淚去實現(xiàn)。 那么沒有年終完美總結(jié),來個新年莽撞開始可好。 進擊巨...

    _Suqin 評論0 收藏0
  • 大話javascript 2期:執(zhí)行下文執(zhí)行下文

    摘要:在中,通過棧的存取方式來管理執(zhí)行上下文,我們可稱其為執(zhí)行棧,或函數(shù)調(diào)用棧。因為執(zhí)行中最先進入全局環(huán)境,所以處于棧底的永遠是全局環(huán)境的執(zhí)行上下文。 一、什么是執(zhí)行上下文? 執(zhí)行上下文(Execution Context): 函數(shù)執(zhí)行前進行的準備工作(也稱執(zhí)行上下文環(huán)境) JavaScript在執(zhí)行一個代碼段之前,即解析(預(yù)處理)階段,會先進行一些準備工作,例如掃描JS中var定義的變量、...

    denson 評論0 收藏0
  • 從底層看JS執(zhí)行機制

    摘要:作用域鏈用于表明上下文的執(zhí)行順序。當前上下文執(zhí)行完畢則出棧,執(zhí)行下一個上下文。 從一個簡單的例子出發(fā) 先從一個簡單的例子出發(fā)(先不涉及異步),看看自己是否大致了解瀏覽器的執(zhí)行機制: console.log(a); var a=1; function foo(a){ console.log(a); var a=2; console.log(a); } foo(a)...

    thursday 評論0 收藏0

發(fā)表評論

0條評論

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