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