欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入學(xué)習(xí)JavaScript執(zhí)行上下文

 更新時(shí)間:2022年08月08日 09:19:12   作者:尤可愛???????  
這篇文章主要介紹了深入學(xué)習(xí)JavaScript執(zhí)行上下文,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助

前言

我們先不看這個(gè)標(biāo)題,來看下面這段代碼是怎么運(yùn)行的:

var num1=1
var num1=2
var result=num1+num2
console.log(result)

我相信,小伙伴都知道打印的是3把,這也太簡(jiǎn)單了,但是我們思考下,這段代碼執(zhí)行時(shí),到底進(jìn)行了怎樣的操作,這里我們要引進(jìn)一個(gè)概念:初始化全局對(duì)象和執(zhí)行上下文

初始化全局對(duì)象(GO)

JS引擎在解析代碼的時(shí)候,會(huì)在堆內(nèi)存中創(chuàng)建一個(gè)全局對(duì)象叫:Gobal Object(GO)

  • 該對(duì)象所有的作用域都可以訪問
  • 里面會(huì)包含Date Array String Number setTimeout setInterval 等等
  • 還有一個(gè)windows屬性指向本身

執(zhí)行上下文

代碼運(yùn)行時(shí):js引擎(這里考慮V8引擎)會(huì)創(chuàng)建執(zhí)行上下文棧(Execution context stack)簡(jiǎn)稱ECS,它就是執(zhí)行代碼的調(diào)用棧

執(zhí)行上下文分為:

  • 全局執(zhí)行上下文( GEC )
  • 函數(shù)執(zhí)行上下文( FEC )

這里我們先分析下全局執(zhí)行上下文,因?yàn)槲覀冮_頭那段代碼是全局代碼

全局執(zhí)行上下文

在執(zhí)行全局代碼的時(shí)候,會(huì)創(chuàng)建全局執(zhí)行上下文( GEC ),GEC會(huì)被放入ECS中去執(zhí)行 GEC被放入ECS

包含兩部分:

  • 第一部分:在代碼執(zhí)行前,也就是V8引擎將parser轉(zhuǎn)成AST的過程中 ( 這里會(huì)涉及到V8引擎在解析js代碼的過程,會(huì)開篇專題講這個(gè)),會(huì)將全局定義的變量放入GO中,但是并不會(huì)賦值,因?yàn)槭?strong>解析階段 (pass:這個(gè)過程也被叫做變量的作用域提升
  • 第二部分:執(zhí)行代碼,并為GO里面的變量賦值,或者執(zhí)行其他函數(shù) 流程圖如下:圖中執(zhí)行前是上面描述的第一部分,開始執(zhí)行代碼是第二部分

Java Script遇到函數(shù)代碼如何執(zhí)行?

當(dāng)js引擎遇到函數(shù)執(zhí)行時(shí),會(huì)創(chuàng)建一個(gè) 函數(shù)執(zhí)行上下文( Functional Execution Contex ) 簡(jiǎn)稱FEC,并壓入到執(zhí)行上下文棧ECS

FEC中包含三部分內(nèi)容:

  • 第一部分:VO(variable object ) 對(duì)象,其實(shí)也是AO( Activation Object )
  • 第二部分:作用域鏈(scope chain):由自己的VO+父級(jí)的VO,查找時(shí)會(huì)一層一層去查找
  • 第三部分:this綁定( 這里不做詳細(xì)描述,后續(xù)會(huì)出專題 )

作用域是解析編譯的時(shí)候就決定了,并不是執(zhí)行調(diào)用的時(shí)候來我們看一段代碼,一起看一下函數(shù)的執(zhí)行過程,一起來思考下這段代碼的運(yùn)行結(jié)果

var message = "Global"
function foo() {
  console.log(message)
}
function bar() {
  var message = "Bar"
  foo()
}
bar()

畫個(gè)圖分析一下吧

首先初始化全局對(duì)象GO,里面有Array、date、setTime等等,還有自己定義的 message對(duì)象初始值為undefined,foo和bar函數(shù)對(duì)象

開始執(zhí)行代碼前,會(huì)創(chuàng)建一個(gè)執(zhí)行上下文棧ESC,開始執(zhí)行全局代碼,所以會(huì)創(chuàng)建一個(gè)全局執(zhí)行上下文棧GEC,將GEC壓入棧底,全局執(zhí)行上下文包括兩部分:
第一部分代碼執(zhí)行前的VO對(duì)象(這里的VO指向的是GO)
第二部分是開始執(zhí)行代碼,執(zhí)行第一行時(shí) var message="Global",GO對(duì)象里的message就被改為Global 

執(zhí)行完第一行后,開始執(zhí)行第9行代碼 bar(),這里是函數(shù)的調(diào)用執(zhí)行,js引擎會(huì)創(chuàng)建一個(gè)函數(shù)執(zhí)行上下文FEC,壓入棧中,FEC包含三部分:

第一部分:VO對(duì)象,這里指向bar自己的AO對(duì)象(包括形參和函數(shù)中定義的變量)
第二部分:作用域鏈scope chain,自己的VO對(duì)象+parent VO對(duì)象

第三部分:this綁定,這里是指向windows(這個(gè)后續(xù)會(huì)開專題講)
開始執(zhí)行bar函數(shù)里面的代碼,var message="Bar",會(huì)將bar的AO對(duì)象的message變量值從undefined改為"Bar",接下來在執(zhí)行foo()函數(shù),注意:此時(shí)bar函數(shù)還沒彈出棧,因?yàn)閒oo函數(shù)還在執(zhí)行

訪問一個(gè)變量的時(shí)候,會(huì)沿著作用域鏈一層一層往上找,最后沒有找到則會(huì)報(bào)錯(cuò)

執(zhí)行到bar函數(shù)的最后一行代碼是foo(),此時(shí)又是一個(gè)函數(shù)的調(diào)用執(zhí)行,又會(huì)創(chuàng)建一個(gè)foo的函數(shù)執(zhí)行上下文,也包含上述的三部分:VO對(duì)象(指向foo的AO對(duì)象) 作用域鏈 和this綁定
開始執(zhí)行foo函數(shù)代碼console.log(message),當(dāng)打印message的時(shí)候,會(huì)沿著作用域鏈一層層找,foo的作用域鏈?zhǔn)亲约旱腁O+父級(jí)的VO(也就是GO對(duì)象),自己的AO對(duì)象為空,所以找到GO里面的message變量,最終打印"Global" 

執(zhí)行完后,函數(shù)執(zhí)行上下文執(zhí)行完之后,就會(huì)彈出棧,foo的FEC先彈出棧,然后bar的FEC彈出棧,他們自個(gè)的AO對(duì)象最終也被釋放

環(huán)境變量和記錄

我們上述所說的VO是基于早期的ECMAS規(guī)范,官網(wǎng)是這樣說的:

 這里借助coderwhy的翻譯:每個(gè)執(zhí)行上下文都關(guān)聯(lián)一個(gè)變量對(duì)象(Vriable Object),在源代碼中變量和函數(shù)的聲明會(huì)被作為屬性加入到變量對(duì)象中,對(duì)于函數(shù)來說,參數(shù)也會(huì)被加入到VO中但是ECMA5以后的版本,官網(wǎng)做了一些詞匯用語(yǔ)的修改 

每個(gè)執(zhí)行上下文都會(huì)關(guān)聯(lián)一個(gè)變量環(huán)境(variable Environment),在執(zhí)行代碼中變量和函數(shù)的聲明會(huì)被當(dāng)做環(huán)境記錄(Environment Record)加入到變量環(huán)境中。
對(duì)于函數(shù)代碼,形參也會(huì)被當(dāng)做環(huán)境記錄加入到變量環(huán)境中

總結(jié):

  • 在訪問一個(gè)變量時(shí),會(huì)沿著作用域鏈一層層往上找,最終沒找到,會(huì)報(bào)錯(cuò):未定義
  • 作用域以及父級(jí)作用域是代碼在編譯階段就已經(jīng)確定了,和調(diào)用位置沒關(guān)系

匯總一些名詞解釋,我們來解釋一下:

名詞解釋
ECS執(zhí)行上下文棧 (Execution Context Stack),也可稱為調(diào)用棧
GEC全局執(zhí)行上下文(Global Execution Context),在執(zhí)行全局代碼前創(chuàng)建
FEC函數(shù)執(zhí)行上下文(Functional Execution Context),在執(zhí)行函數(shù)前創(chuàng)建
VOVariable Object,早期ECMA規(guī)范中的變量環(huán)境,對(duì)應(yīng)Object
VEVariable Environment,最新ECMA規(guī)范中的變量環(huán)境,對(duì)應(yīng)環(huán)境記錄
GO全局對(duì)象(Global Object),解析全局代碼時(shí)創(chuàng)建,GEC中關(guān)聯(lián)的VO就是GO
AO活動(dòng)對(duì)象(Activation Object),VO被激活就變成了AO,VO和AO本質(zhì)上是一個(gè)東西,它們其實(shí)都是同一個(gè)對(duì)象,只是處于執(zhí)行環(huán)境的不同生命周期

到此這篇關(guān)于深入學(xué)習(xí)JavaScript執(zhí)行上下文的文章就介紹到這了,更多相關(guān)JS執(zhí)行上下文內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論