摘要:一系列活動(dòng)的執(zhí)行上下文從邏輯上形成一個(gè)棧。堆棧中的上下文就會(huì)被依次執(zhí)行并且彈出堆棧,直到回到全局的上下文。確定上下文中的指向?qū)ο蟠_定指向或當(dāng)前對(duì)象。
定義
執(zhí)行上下文(也稱執(zhí)行環(huán)境execution context)(簡(jiǎn)稱:EC)是個(gè)抽象的概念,是在函數(shù)被調(diào)用時(shí),但是在函數(shù)體被真正執(zhí)行以前所創(chuàng)建的。每個(gè)執(zhí)行上下文都有一個(gè)變量對(duì)象(variable object),保存著當(dāng)前環(huán)境中所有的變量或函數(shù)聲明或形參arguments以及this。
?? 一系列活動(dòng)的執(zhí)行上下文從邏輯上形成一個(gè)棧。棧底總是全局上下文,棧頂是當(dāng)前(活動(dòng)的)執(zhí)行上下文。當(dāng)執(zhí)行流進(jìn)入函數(shù)時(shí),函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中,在函數(shù)執(zhí)行之后,棧再將其環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。
?? 代碼在一個(gè)環(huán)境中執(zhí)行,會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈,作用域鏈保證了執(zhí)行的順序。
全局:
?? 只存在一個(gè)全局的上下文,該上下文能被任何其它的上下文所訪問(wèn)到。
函數(shù):
?? 每調(diào)用執(zhí)行一個(gè)函數(shù)時(shí),引擎就會(huì)自動(dòng)新建出一個(gè)函數(shù)執(zhí)行上下文,就是新建一個(gè)局部作用域,可以在該局部作用域中聲明私有變量等,在外部的上下文中是無(wú)法直接訪問(wèn)到該局部作用域內(nèi)的元素的。
?? 當(dāng)在全局上下文中調(diào)用執(zhí)行一個(gè)函數(shù)時(shí),程序流就進(jìn)入該被調(diào)用函數(shù)內(nèi),此時(shí)引擎就會(huì)為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文(即使是調(diào)用自身函數(shù)),并且將其壓入到執(zhí)行上下文堆棧的頂部。瀏覽器總是執(zhí)行當(dāng)前在堆棧頂部的上下文,一旦執(zhí)行完畢,該上下文就會(huì)從堆棧頂部被彈出,然后,進(jìn)入最新的堆棧頂部的上下文執(zhí)行代碼。堆棧中的上下文就會(huì)被依次執(zhí)行并且彈出堆棧,直到回到全局的上下文。
eval函數(shù)
??在eval函數(shù)內(nèi)運(yùn)行的代碼。
執(zhí)行上下文建立、運(yùn)行過(guò)程 建立階段:建立variableObject對(duì)象發(fā)生在調(diào)用一個(gè)函數(shù)時(shí),但是在執(zhí)行函數(shù)體內(nèi)具體的代碼以前。
先是處理arguments參數(shù),接著是函數(shù)的聲明,最后是變量的聲明。
??建立arguments對(duì)象,檢查當(dāng)前上下文中的參數(shù),建立該對(duì)象下的屬性以及屬性值。每個(gè)執(zhí)行環(huán)境都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象(variable object),環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中。雖然我們編寫(xiě)的代碼無(wú)法訪問(wèn)這個(gè)對(duì)象,但解析器在處理數(shù)據(jù)時(shí)會(huì)在后臺(tái)使用它。
??檢查當(dāng)前上下文中的函數(shù)聲明:找到函數(shù)聲明的函數(shù)名,在variableObject下面用該函數(shù)名建立一個(gè)屬性,屬性值就是指向該函數(shù)在內(nèi)存中的地址的一個(gè)引用;如果上述函數(shù)名已經(jīng)存在于variableObject下,那么對(duì)應(yīng)的屬性值會(huì)被新的引用所覆蓋。
?? 檢查當(dāng)前上下文中的變量聲明:每找到一個(gè)變量的聲明,就在variableObject下,用變量名建立一個(gè)屬性,屬性值為undefined。如果該變量名已經(jīng)存在于variableObject屬性中,直接跳過(guò)(防止指向函數(shù)的屬性的值被變量屬性覆蓋為undefined),原屬性值不會(huì)被修改。
初始化作用域鏈??每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境。當(dāng)執(zhí)行流進(jìn)入一個(gè)函數(shù)時(shí),函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中。而在函數(shù)執(zhí)行之后,棧將其環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。 ECMAScript 程序中的執(zhí)行流正是由這個(gè)方便的機(jī)制控制著。當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈(scope chain)。作用域鏈的用途,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)的有序訪問(wèn)。作用域鏈的前端,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象。如果這個(gè)環(huán)境是函數(shù),則將其活動(dòng)對(duì)象(activation object)作為變量對(duì)象。活動(dòng)對(duì)象在最開(kāi)始時(shí)只包含一個(gè)變量,即 arguments 對(duì)象(這個(gè)對(duì)象在全局環(huán)境中是不存在的)。作用域鏈中的下一個(gè)變量對(duì)象來(lái)自包含(外部)環(huán)境,而再下一個(gè)變量對(duì)象則來(lái)自下一個(gè)包含環(huán)境。這樣,一直延續(xù)到全局執(zhí)行環(huán)境;全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象。
確定上下文中this的指向?qū)ο?/b>??確定this指向window或當(dāng)前對(duì)象。
代碼執(zhí)行階段給variableObject中的變量賦值
function aoo(i){ var a = "staven"; var b = function boo(){ }; function coo(){ } } aoo(1);
調(diào)用aoo(1),建立階段執(zhí)行下上文對(duì)象:
aooExecutionContext = { variableObject:{ arguments:{ 0:1, length:1 }, i:1, coo:(指向function coo()), a:undefined, b:undefined }, scopeChain:{……}, this:{……} };
運(yùn)行階段,執(zhí)行上下文對(duì)象:
aooExecutionContext = { variableObject:{ arguments:{ 0:1, length:1 }, i:1, coo:(指向function coo()), a:"staven", b:(指向function boo()) }, scopeChain:{……}, this:{……} };解析變量提升
(function(){ console.log(typeof foo); //function console.log(typeof bar); //undefined var foo = "hello", bar = function(){ return "staven"; }; function foo(){ return "hello"; } console.log(typeof foo); //string console.log(typeof bar); //function }());
??因?yàn)樵谏舷挛牡慕㈦A段,先是處理arguments, 參數(shù),接著是函數(shù)的聲明,最后是變量的聲明。那么,發(fā)現(xiàn)foo函數(shù)的聲明后,就會(huì)在variableObject下面建立一個(gè)foo屬性,其值是一個(gè)指向函數(shù)的引用。當(dāng)處理變量聲明的時(shí)候,發(fā)現(xiàn)有var foo的聲明,但是variableObject已經(jīng)具有了foo屬性,所以直接跳過(guò)。當(dāng)進(jìn)入代碼執(zhí)行階段的時(shí)候,就可以通過(guò)訪問(wèn)到foo屬性了,因?yàn)樗呀?jīng)就存在,并且是一個(gè)函數(shù)引用。
??bar是變量的聲明,在建立階段的時(shí)候,被賦予的默認(rèn)的值為undefined。由于它只要在代碼執(zhí)行階段才會(huì)被賦予具體的值,所以,當(dāng)調(diào)用typeof(bar)的時(shí)候輸出的值為undefined。
???深究JavaScript系列???
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/87889.html
摘要:構(gòu)造器的目的是要?jiǎng)?chuàng)建一個(gè)新對(duì)象并對(duì)其進(jìn)行設(shè)置,然后將其作為構(gòu)造器的返回值進(jìn)行返回,是通過(guò)函數(shù)調(diào)用初始化創(chuàng)建新對(duì)象。或方法進(jìn)行調(diào)用通過(guò)或調(diào)用函數(shù),被調(diào)用的函數(shù)的指向第一個(gè)參數(shù)指向的。 this ??JavaScript的this總是指向一個(gè)對(duì)象,而這個(gè)對(duì)象是基于函數(shù)運(yùn)行時(shí)動(dòng)態(tài)綁定的,并非函數(shù)聲明時(shí)綁定。 函數(shù)調(diào)用方式 作為對(duì)象的方法調(diào)用 作為普通函數(shù)進(jìn)行調(diào)用 作為構(gòu)造器進(jìn)行調(diào)用 通過(guò)a...
摘要:前言最近加入到新項(xiàng)目組負(fù)責(zé)前端技術(shù)預(yù)研和選型,一直偏向于以為代表的技術(shù)線,于是查閱各類(lèi)資料想說(shuō)服老大向這方面靠,最后得到的結(jié)果是資料是英語(yǔ)無(wú)所謂,最重要是上符合要求,技術(shù)的事你說(shuō)了算。但當(dāng)我們需要?jiǎng)討B(tài)實(shí)例化元素時(shí),命令式則是最佳的選擇。 前言 ?最近加入到新項(xiàng)目組負(fù)責(zé)前端技術(shù)預(yù)研和選型,一直偏向于以Polymer為代表的WebComponent技術(shù)線,于是查閱各類(lèi)資料想說(shuō)服老大向這方面...
摘要:函數(shù)是中唯一擁有自身作用域的結(jié)構(gòu),因此閉包的創(chuàng)建依賴于函數(shù)。閉包中的匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此其對(duì)象通常指向在通過(guò)或改變函數(shù)執(zhí)行環(huán)境的情況下,就會(huì)指向其他對(duì)象。當(dāng)匿名函數(shù)執(zhí)行完畢,其作用域鏈立即銷(xiāo)毀,從而可以減少閉包占用資源問(wèn)題。 概念 ??閉包是指能夠引用外部函數(shù)中的局部變量的函數(shù),并導(dǎo)致外部函數(shù)調(diào)用后函數(shù)對(duì)象與局部變量無(wú)法及時(shí)銷(xiāo)毀。函數(shù)是JavaScript中唯一擁有自身作...
摘要:有意思的是,這意味著變量在聲明之前甚至已經(jīng)可用。的這個(gè)特性被非正式地稱為聲明提前,即函數(shù)里聲明的所有變量但不涉及賦值都被提前至函數(shù)體的頂部。但實(shí)際上會(huì)將其看成兩個(gè)聲明和。第二個(gè)賦值聲明會(huì)被留在原地等待執(zhí)行階段。 簡(jiǎn)介 JavaScript的函數(shù)作用域是指在函數(shù)內(nèi)聲明的所有變量在函數(shù)體內(nèi)始終是可見(jiàn)的。有意思的是,這意味著變量在聲明之前甚至已經(jīng)可用。JavaScript的這個(gè)特性被非正式地...
摘要:在操作對(duì)象時(shí),實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象。任一變量值操作互不影響。訪問(wèn)變量有按值和按引用兩種方式,而參數(shù)只能按值傳遞。基本類(lèi)型參數(shù)傳遞傳給函數(shù)的是數(shù)值的一個(gè)復(fù)制,函數(shù)中對(duì)其的修改外部不可見(jiàn)。 ?? ECMAScript 變量可能包含兩種不同數(shù)據(jù)類(lèi)型的值:基本類(lèi)型值和引用類(lèi)型值。 基本類(lèi)型值指的是簡(jiǎn)單的數(shù)據(jù)段,而引用類(lèi)型值指那些可能由多個(gè)值構(gòu)成的對(duì)象。 ??5 種基本數(shù)據(jù)類(lèi)...
閱讀 1014·2021-11-22 14:56
閱讀 975·2021-11-11 16:54
閱讀 7557·2021-09-23 11:55
閱讀 3000·2021-09-22 15:57
閱讀 2788·2021-08-27 16:25
閱讀 667·2019-08-30 15:55
閱讀 1657·2019-08-30 15:43
閱讀 1593·2019-08-30 14:23