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