摘要:深入系列第七篇,結(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)侨绾巫兓摹?/p>
在《JavaScript深入之執(zhí)行上下文?!分兄v到,當(dāng) JavaScript 代碼執(zhí)行一段可執(zhí)行代碼(executable code)時,會創(chuàng)建對應(yīng)的執(zhí)行上下文(execution context)。
對于每個執(zhí)行上下文,都有三個重要屬性:
變量對象(Variable object,VO)
作用域鏈(Scope chain)
this
然后分別在《JavaScript深入之變量對象》、《JavaScript深入之作用域鏈》、《JavaScript深入之從ECMAScript規(guī)范解讀this》中講解了這三個屬性。
閱讀本文前,如果對以上的概念不是很清楚,希望先閱讀這些文章。
因為,這一篇,我們會結(jié)合著所有內(nèi)容,講講執(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()();
兩段代碼都會打印"local scope"。雖然兩段代碼執(zhí)行的結(jié)果一樣,但是兩段代碼究竟有哪些不同呢?
緊接著就在下一篇《JavaScript深入之執(zhí)行上下文?!分?,講到了兩者的區(qū)別在于執(zhí)行上下文棧的變化不一樣,然而,如果是這樣籠統(tǒng)的回答,依然顯得不夠詳細(xì),本篇就會詳細(xì)的解析執(zhí)行上下文棧和執(zhí)行上下文的具體變化過程。
具體執(zhí)行分析我們分析第一段代碼:
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f(); } checkscope();
執(zhí)行過程如下:
1.執(zhí)行全局代碼,創(chuàng)建全局執(zhí)行上下文,全局上下文被壓入執(zhí)行上下文棧
ECStack = [ globalContext ];
2.全局上下文初始化
globalContext = { VO: [global, scope, checkscope], Scope: [globalContext.VO], this: globalContext.VO }
2.初始化的同時,checkscope 函數(shù)被創(chuàng)建,保存作用域鏈到函數(shù)的內(nèi)部屬性[[scope]]
checkscope.[[scope]] = [ globalContext.VO ];
3.執(zhí)行 checkscope 函數(shù),創(chuàng)建 checkscope 函數(shù)執(zhí)行上下文,checkscope 函數(shù)執(zhí)行上下文被壓入執(zhí)行上下文棧
ECStack = [ checkscopeContext, globalContext ];
4.checkscope 函數(shù)執(zhí)行上下文初始化:
復(fù)制函數(shù) [[scope]] 屬性創(chuàng)建作用域鏈,
用 arguments 創(chuàng)建活動對象,
初始化活動對象,即加入形參、函數(shù)聲明、變量聲明,
將活動對象壓入 checkscope 作用域鏈頂端。
同時 f 函數(shù)被創(chuàng)建,保存作用域鏈到 f 函數(shù)的內(nèi)部屬性[[scope]]
checkscopeContext = { AO: { arguments: { length: 0 }, scope: undefined, f: reference to function f(){} }, Scope: [AO, globalContext.VO], this: undefined }
5.執(zhí)行 f 函數(shù),創(chuàng)建 f 函數(shù)執(zhí)行上下文,f 函數(shù)執(zhí)行上下文被壓入執(zhí)行上下文棧
ECStack = [ fContext, checkscopeContext, globalContext ];
6.f 函數(shù)執(zhí)行上下文初始化, 以下跟第 4 步相同:
復(fù)制函數(shù) [[scope]] 屬性創(chuàng)建作用域鏈
用 arguments 創(chuàng)建活動對象
初始化活動對象,即加入形參、函數(shù)聲明、變量聲明
將活動對象壓入 f 作用域鏈頂端
fContext = { AO: { arguments: { length: 0 } }, Scope: [AO, checkscopeContext.AO, globalContext.VO], this: undefined }
7.f 函數(shù)執(zhí)行,沿著作用域鏈查找 scope 值,返回 scope 值
8.f 函數(shù)執(zhí)行完畢,f 函數(shù)上下文從執(zhí)行上下文棧中彈出
ECStack = [ checkscopeContext, globalContext ];
9.checkscope 函數(shù)執(zhí)行完畢,checkscope 執(zhí)行上下文從執(zhí)行上下文棧中彈出
ECStack = [ globalContext ];
第二段代碼就留給大家去嘗試模擬它的執(zhí)行過程。
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f; } checkscope()();
不過,在下一篇《JavaScript深入之閉包》中也會提及這段代碼的執(zhí)行過程。
下一篇文章《JavaScript深入之閉包》
相關(guān)鏈接《JavaScript深入之詞法作用域和動態(tài)作用域》
《JavaScript深入之執(zhí)行上下文?!?/p>
《JavaScript深入之變量對象》
《JavaScript深入之作用域鏈》
《JavaScript深入之從ECMAScript規(guī)范解讀this》
重要參考《一道js面試題引發(fā)的思考》
本文寫的太好,給了我很多啟發(fā)。感激不盡!
深入系列JavaScript深入系列目錄地址:https://github.com/mqyqingfeng/Blog。
JavaScript深入系列預(yù)計寫十五篇左右,旨在幫大家捋順JavaScript底層知識,重點講解如原型、作用域、執(zhí)行上下文、變量對象、this、閉包、按值傳遞、call、apply、bind、new、繼承等難點概念。
如果有錯誤或者不嚴(yán)謹(jǐn)?shù)牡胤?,請?wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎star,對作者也是一種鼓勵。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/82474.html
摘要:下面,讓我們以一個函數(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í)行代...
摘要:深入系列第八篇,介紹理論上的閉包和實踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。定義對閉包的定義為閉包是指那些能夠訪問自由變量的函數(shù)。 JavaScript深入系列第八篇,介紹理論上的閉包和實踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。 定義 MDN 對閉包的定義為: 閉包是指那些能夠訪問自由變量的函數(shù)。 那什么是自由變量呢? 自由變量是指在函數(shù)中使用的,但既不是函數(shù)參數(shù)也...
摘要:深入系列第三篇,講解執(zhí)行上下文棧的是如何執(zhí)行的,也回答了第二篇中的略難的思考題。 JavaScript深入系列第三篇,講解執(zhí)行上下文棧的是如何執(zhí)行的,也回答了第二篇中的略難的思考題。 順序執(zhí)行? 如果要問到 JavaScript 代碼執(zhí)行順序的話,想必寫過 JavaScript 的開發(fā)者都會有個直觀的印象,那就是順序執(zhí)行,畢竟: var foo = function () { ...
摘要:本計劃一共期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃,點擊查看前端進階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對象,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第一期,本周的主題是調(diào)用堆棧,今天是第二天。 本計劃一共28期,每期...
摘要:深入系列第四篇,具體講解執(zhí)行上下文中的變量對象與活動對象。下一篇文章深入之作用域鏈本文相關(guān)鏈接深入之執(zhí)行上下文棧深入系列深入系列目錄地址。 JavaScript深入系列第四篇,具體講解執(zhí)行上下文中的變量對象與活動對象。全局上下文下的變量對象是什么?函數(shù)上下文下的活動對象是如何分析和執(zhí)行的?還有兩個思考題幫你加深印象,快來看看吧! 前言 在上篇《JavaScript深入之執(zhí)行上下文?!分?..
閱讀 2224·2019-08-30 15:54
閱讀 1960·2019-08-30 13:49
閱讀 679·2019-08-29 18:44
閱讀 834·2019-08-29 18:39
閱讀 1117·2019-08-29 15:40
閱讀 1538·2019-08-29 12:56
閱讀 3151·2019-08-26 11:39
閱讀 3104·2019-08-26 11:37