站長資訊網
        最全最豐富的資訊網站

        一文聊聊Javascript中的執行上下文

        本篇文章帶大家聊聊Javascript中的執行上下文,分享一個思考題,通過對思考題的分析,想必會對執行上下文有更加深入的理解。

        一文聊聊Javascript中的執行上下文

        在前面的幾篇文章中,我們深入了解了關于執行上下文的三個重要成員:變量對象、作用域鏈和 this ,本篇文章是前四篇文章的的內容的集合,聚合分散的知識點,做一個簡單的鞏固。不知道有沒有人是上一篇來的,我們的上一篇留下了一個思考題,通過對思考題的分析,想必會對執行上下文有更加深入的理解。

        思考題

        這里為了稍微將案例復雜化一點,做了一點點修改,但是并沒有改變原題所考察的點。

        function func(value){     getValue = function(){         console.log(value);     };     return this }              function getValue(){     console.log(5); }  Func(1).getValue(); //為什么是1呢?
        登錄后復制

        具體執行分析

        執行全局代碼,創建全局執行上下文,全局上下文被壓入執行上下文棧

        ECStack = [ globalContext ];
        登錄后復制

        登錄后復制

        初始化全局上下文

        globalContext = {     VO: {         func: reference to function func(){},         getValue: reference to function getValue(){}     },     Scope: [globalContext.VO],     this: globalContext.VO //全局上下文 }
        登錄后復制

        初始化全局上下文同時創建了兩個函數,因此也會保存他們父級作用域鏈在他們的內部屬性 [[scope]] 內

        func.[[scope]] = [      globalContext.VO ]; getValue.[[scope]] = [      globalContext.VO ];
        登錄后復制

        此時開始執行代碼,執行到最后的語句時先執行 func 函數,也就創建按步驟 func 函數執行上下文:

        • 復制函數 [[scope]] 屬性創建作用域鏈

        • 用 arguments 創建活動對象

        • 初始化活動對象

        • 將活動對象壓入 checksfunccope 作用域鏈頂端。

        • 創建this,簡單分析:MemberExpression 值為func,func是一個函數對象,理所當然是一個Reference ,其中它的 base value 是 EnvironmentRecord ,所以它的 this 值為 ImplicitThisValue(ref),返回值始終是 undefined ,非嚴格模式下,其值會被隱式轉換為全局對象。

        funcContext = {     AO: {         arguments: { // 數組             0: 1,             length: 1         }     },     Scope: [AO, globalContext.VO],     this: undefined }
        登錄后復制

        可能有人會有疑問,func 里的 getValue 呢?,因為它并沒有變量申明,因此他其實是一個屬性的賦值操作,在后面運行時才會被執行。

        創建函數執行上下文后壓入執行上下文棧

            ECStack = [         funcContext,         globalContext     ];
        登錄后復制

        函數開始執行,此時就是為什么最后輸出是1的關鍵了,第一句賦值操作,那么就需要沿著執行上下文去找變量 getValue,那么我們就來看 funcContext 中的作用域,首先找到 funcContext.AO 顯然并不存在 getValue 這一屬性,那么沿著作用域鏈往上找,找到了globalContext.VO ,找到了 getValue ,這時候就會給全局作用域下的 getValue 屬性重新賦值,賦的是一個函數的傳新版本,也就重新創建了函數作用域,將這個全新的 getValue 函數的父級作用域鏈保存在它在他們的內部屬性 [[scope]] 內:

        getValue .[[scope]] = [ funcContext.AO, globalContext.VO ];
        登錄后復制

        然后才繼續返回 this ,查找 funcContext 的 this ,即返回undefined;func 執行上下文出棧

        ECStack = [ globalContext ];
        登錄后復制

        登錄后復制

        繼續執行Func(1).getValue(),前半部分返回了 undefined ,此時系統隱式轉換為全局變量對象,從全局變量對象中找到 getValue 屬性。這時候我們發現 getValue 早已不是當年那個少年,執行全新的 getValue 的函數執行上下文并入棧:

        getValueContext = {     AO: {         arguments: { // 數組             length: 0         }     },     Scope: [ AO, funcContext.AO, globalContext.VO ],     this: undefined } ECStack = [     getValueContext,     globalContext  ];
        登錄后復制

        函數開始執行,發現她要輸出 value ,沿著作用域去找,getValueContext.AO 中并沒有這個屬性, 繼續往下找找到 funcContext.AO(注意! ),在形參中 找到了 value 那么就輸出對樣的值,也就輸出了1。

        函數執行完畢,getValueContext 和 globalContext 相繼出棧并銷毀,代碼運行完畢。

        總結

        本片以一個簡單但又不簡單的示例,將前面的四篇文章串聯起來,完整地分析了JS代碼執行時執行上下文的工作過程,希望大家對此能有更深的理解。但是,不知道有沒有細心的同學發現,上面的示例中,執行 getValue 函數的過程中,由尋找屬性 value的步驟(標記位置),那個時候 func 函數明明已經執行完畢了,他的執行上下文已經出棧了,為什么還能從他的執行上下文中找到 value 屬性呢?這其實就是閉包產生的原理了,下一篇我們仍然用這個示例去學習閉包產生的原理。

        【推薦學習:javascript高級教程】

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 人精品影院| 99久久精品九九亚洲精品| 亚洲爆乳精品无码一区二区三区 | 久久久久久亚洲精品成人| 亚洲AV无码久久精品色欲| 日韩精品无码一区二区三区不卡 | 精品久久久无码中文字幕天天| 久久精品国产亚洲7777| 亚洲成网777777国产精品| 无码精品A∨在线观看| 国产在线精品一区二区夜色 | 色妞ww精品视频7777| 精品国产一区二区22| 88国产精品无码一区二区三区| 93精91精品国产综合久久香蕉| 亚洲精品成人片在线观看精品字幕| 国产精品无码久久四虎| 亚洲国产精品毛片av不卡在线| 97久人人做人人妻人人玩精品 | 国产精品久久毛片完整版| 亚洲国产精品尤物yw在线| www.亚洲精品| 久久国产午夜精品一区二区三区| 久久国产精品-国产精品| 久久精品无码专区免费| 亚洲精品欧美综合在线| 亚洲欧美精品一区久久中文字幕| 亚洲国产美女精品久久久久∴| 精品亚洲一区二区三区在线观看 | 久草热8精品视频在线观看| 国产精品成人精品久久久| 亚洲午夜成人精品电影在线观看| 国产成人无码精品久久久免费| 久久精品国产影库免费看| 亚洲欧美一级久久精品 | 国产精品91在线| 国产福利91精品一区二区三区| 国产成人无码精品一区二区三区| 国产乱人伦偷精品视频 | 99re这里只有精品6| 91精品国产综合久久久久久|