當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
JS高级——函数执行、作用域链内存结构图
生活随笔
收集整理的這篇文章主要介紹了
JS高级——函数执行、作用域链内存结构图
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、JavaScript的執(zhí)行過程
假如我們有下面一段代碼,它在JavaScript中是如何被執(zhí)行的呢?
1.1 第一步:初始化全局對象
- js引擎會在執(zhí)行代碼之前,會在堆內(nèi)存中創(chuàng)建一個全局對象:Global Object(GO)
- 該對象 所有的作用域(scope)都可以訪問;
- 里面會包含Date、Array、String、Number、setTimeout、setInterval等等;
- 其中還有一個window屬性指向自己;
1.2 執(zhí)行上下文棧(調(diào)用棧)
js引擎內(nèi)部有一個執(zhí)行上下文棧(Execution Context Stack,簡稱ECS),它是用于執(zhí)行代碼的調(diào)用棧。
那么現(xiàn)在它要執(zhí)行誰呢?執(zhí)行的是全局的代碼塊:
- 全局的代碼塊為了執(zhí)行會構(gòu)建一個 Global Execution Context(全局執(zhí)行上下文)(GEC);
- GEC(全局執(zhí)行上下文)會 被放入到ECS(執(zhí)行上下文棧)中 執(zhí)行;
GEC被放入到ECS中里面包含兩部分內(nèi)容:
- 第一部分:在代碼執(zhí)行前,在parser轉(zhuǎn)成AST的過程中,會將全局定義的變量、函數(shù)等加入到GlobalObject中,但是并不會賦值; 這個過程也稱之為變量的作用域提升(hoisting)
- 第二部分:在代碼執(zhí)行中,對變量賦值,或者執(zhí)行其他的函數(shù);
1.3 第二步:將全局執(zhí)行上下文放入執(zhí)行上下文棧中
1.4 第三步:全局執(zhí)行上下文開始執(zhí)行代碼
二、遇到函數(shù)如何執(zhí)行?
在執(zhí)行的過程中執(zhí)行到一個函數(shù)時,就會根據(jù)函數(shù)體創(chuàng)建一個函數(shù)執(zhí)行上下文(Functional Execution
Context,簡稱FEC),并且壓入到EC Stack中。
FEC中包含三部分內(nèi)容:
- 第一部分:在解析函數(shù)成為AST樹結(jié)構(gòu)時,會創(chuàng)建一個Activation Object(AO):
AO中包含形參、arguments、函數(shù)定義和指向函數(shù)對象、定義的變量; - 第二部分:作用域鏈:由VO(在函數(shù)中就是AO對象)和父級VO組成,查找時會一層層查找;
- 第三部分:this綁定的值
下面看看如下代碼的執(zhí)行過程:
2.1 第一步:初始化全局對象
2.2 第二步: 將全局執(zhí)行上下文 放入 執(zhí)行上下文棧中
2.3 第三步:全局執(zhí)行上下文 開始執(zhí)行代碼
3.4 第四步:遇到函數(shù)調(diào)用則 創(chuàng)建函數(shù)執(zhí)行上下文FEC,并把FEC放入 執(zhí)行上下文棧ECS中
3.5 第五步:函數(shù)執(zhí)行上下文FEC開始執(zhí)行代碼
最后瀏覽器控制臺輸出: foo
三、練習題:
注意:函數(shù)中的變量沒有使用var關(guān)鍵字來定義時,相當于會在GO對象中定義并保存這個變量,所以即使函數(shù)執(zhí)行完成后,函數(shù)內(nèi)的變量會被銷毀,但是函數(shù)外部仍然可以獲取到這個變量
總結(jié)
以上是生活随笔為你收集整理的JS高级——函数执行、作用域链内存结构图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 办公室分配方案python_Python
- 下一篇: 五、pink老师的学习笔记——CSS精灵