摘要:活動對象的變化與處理上下文的兩個階段密切相關(guān)。所有變量聲明由名稱和對應(yīng)值組成一個變量對象的屬性被創(chuàng)建如果變量名稱跟已經(jīng)聲明的形式參數(shù)或函數(shù)相同,則變量聲明不會干擾已經(jīng)存在的這類屬性。
1 定義
如果變量與執(zhí)行上下文相關(guān),那變量自己應(yīng)該知道它的數(shù)據(jù)存儲在哪里,并且知道如何訪問。這種機(jī)制稱為變量對象(variable object)。
變量對象(縮寫為VO)是一個與執(zhí)行上下文相關(guān)的特殊對象,它存儲著在上下文中聲明的以下內(nèi)容:
變量 (var, 變量聲明);
函數(shù)聲明 (FunctionDeclaration, 縮寫為FD);
函數(shù)的形參
舉例來說,我們可以用普通的ECMAScript對象來表示一個變量對象:
VO = {};
就像我們所說的, VO就是執(zhí)行上下文的屬性(property):
activeExecutionContext = { VO: { // 上下文數(shù)據(jù)(var, FD, function arguments) } };2 全局上下文中的變量對象
全局上下文中的變量對象就是全局對象,所以我們聲明的變量都是全局對象的屬性。
3 函數(shù)上下文中的變量對象函數(shù)上下文中的變量對象由活動對象(AO)扮演。
活動對象的變化與處理上下文的兩個階段密切相關(guān)。進(jìn)入執(zhí)行上下文和執(zhí)行代碼。
3.1 進(jìn)入執(zhí)行上下文當(dāng)進(jìn)入執(zhí)行上下文(代碼執(zhí)行之前)時,VO里已經(jīng)包含了下列屬性:
1. 函數(shù)的所有形參(如果我們是在函數(shù)執(zhí)行上下文中) 由名稱和對應(yīng)值組成的一個變量對象的屬性被創(chuàng)建;沒有傳遞對應(yīng)參數(shù)的話,那么由名稱和undefined值組成的一種變量對象的屬性也將被創(chuàng)建。 2. 所有函數(shù)聲明(FunctionDeclaration, FD) 由名稱和對應(yīng)值(函數(shù)對象(function-object))組成一個變量對象的屬性被創(chuàng)建;如果變量對象已經(jīng)存在相同名稱的屬性,則完全替換這個屬性。 3. 所有變量聲明(var, VariableDeclaration) 由名稱和對應(yīng)值(undefined)組成一個變量對象的屬性被創(chuàng)建;如果變量名稱跟已經(jīng)聲明的形式參數(shù)或函數(shù)相同,則變量聲明不會干擾已經(jīng)存在的這類屬性。
也就是變量提升和var x = undefined 不會影響形參x的值,之后調(diào)用x指向的還是形參。
注意:進(jìn)入執(zhí)行上下文時,函數(shù)聲明和變量聲明都提前,但是變量聲明的值還都是undefined,而函數(shù)聲明的變量已經(jīng)可以指向函數(shù)。變量聲明的優(yōu)先級最低。
讓我們看一個例子:
function test(a, b) { var c = 10; function d() {} var e = function _e() {}; (function x() {}); } test(10); // call
當(dāng)進(jìn)入帶有參數(shù)10的test函數(shù)上下文時,AO表現(xiàn)為如下:
AO(test) = { a: 10, b: undefined, c: undefined, d:e: undefined };
注意,AO里并不包含函數(shù)“x”。這是因為“x” 是一個函數(shù)表達(dá)式(FunctionExpression, 縮寫為 FE) 而不是函數(shù)聲明,函數(shù)表達(dá)式不會影響VO。 不管怎樣,函數(shù)“_e” 同樣也是函數(shù)表達(dá)式,但是就像我們下面將看到的那樣,因為它分配給了變量 “e”,所以它可以通過名稱“e”來訪問。
3.2 代碼執(zhí)行進(jìn)入上下文階段,AO/VO已經(jīng)擁有了屬性(不過,并不是所有的屬性都有值,大部分屬性的值還是系統(tǒng)默認(rèn)的初始值undefined )。
還是前面那個例子, AO/VO在代碼執(zhí)行期間被修改如下:
AO["c"] = 10; AO["e"] =;
另一個經(jīng)典例子:
alert(x); // function var x = 10; alert(x); // 10 x = 20; function x() {}; alert(x); // 20
為什么第一個alert “x” 的返回值是function,而且它還是在“x” 聲明之前訪問的“x” 的?為什么不是10或20呢?因為,根據(jù)規(guī)范函數(shù)聲明是在當(dāng)進(jìn)入上下文時填入的; 同意周期,在進(jìn)入上下文的時候還有一個變量聲明“x”,那么正如我們在上一個階段所說,變量聲明在順序上跟在函數(shù)聲明和形式參數(shù)聲明之后,而且在這個進(jìn)入上下文階段,變量聲明不會干擾VO中已經(jīng)存在的同名函數(shù)聲明或形式參數(shù)聲明,因此,在進(jìn)入上下文時,VO的結(jié)構(gòu)如下:
VO = {}; VO["x"] =// 找到var x = 10; // 如果function "x"沒有已經(jīng)聲明的話 // 這時候"x"的值應(yīng)該是undefined // 但是這個case里變量聲明沒有影響同名的function的值 VO["x"] = //緊接著,在執(zhí)行代碼階段,VO做如下修改: VO["x"] = 10; VO["x"] = 20;
我們可以在第二、三個alert看到這個效果。
在下面的例子里我們可以再次看到,變量是在進(jìn)入上下文階段放入VO中的。(因為,雖然else部分代碼永遠(yuǎn)不會執(zhí)行,但是不管怎樣,變量“b”仍然存在于VO中。)
if (true) { var a = 1; } else { var b = 2; } alert(a); // 1 alert(b); // undefined,不是b沒有聲明,而是b的值是undefined
本文絕大部分內(nèi)容來自: http://dmitrysoshnikov.com/ec...
僅做少許修改
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86610.html
摘要:理解了這句話,我們就可以來看閉包了閉包前面說過,函數(shù)可以訪問函數(shù)作用域鏈中的變量,但如果我們想在函數(shù)外訪問函數(shù)內(nèi)卻不行了。 不管是閉包還是this關(guān)鍵字,都是困擾JS初學(xué)者的比較難懂的東西,如果你對它們的認(rèn)識還不足夠清晰,那么現(xiàn)在就一起把它們掌握掉。還是那句話,我們從最基本的開始,建立起一個非常清晰的知識結(jié)構(gòu),好了,開始吧 ? 閉包 當(dāng)然我們今天說的是javascript里的閉包。要學(xué)...
摘要:全局和上下文中的作用域鏈這里不一定很有趣,但必須要提示一下。全局上下文的作用域鏈僅包含全局對象。代碼的上下文與當(dāng)前的調(diào)用上下文擁有同樣的作用域鏈。代碼執(zhí)行時對作用域鏈的影響在中,在代碼執(zhí)行階段有兩個聲明能修改作用域鏈。 1 定義 我們已經(jīng)知道一個執(zhí)行上下文中的數(shù)據(jù)(參數(shù),變量,函數(shù))作為屬性存儲在變量對象中。 也知道變量對象是在每次進(jìn)入上下文是創(chuàng)建并填入初始值,值的更新出現(xiàn)在代碼執(zhí)行階...
摘要:最后重點理解結(jié)論箭頭函數(shù)的,總是指向定義時所在的對象,而不是運(yùn)行時所在的對象。輸出,箭頭函數(shù)不會綁定所以傳入指向無效。原因是,要徹底理解應(yīng)該是建立在已經(jīng)大致理解了中的執(zhí)行上下文,作用域作用域鏈,閉包,變量對象,函數(shù)執(zhí)行過程的基礎(chǔ)上。 本文共 2025 字,看完只需 8 分鐘 概述 前面的文章講解了 JavaScript 中的執(zhí)行上下文,作用域,變量對象,this 的相關(guān)原理,但是我...
摘要:是完全的面向?qū)ο笳Z言,它們通過類的形式組織函數(shù)和變量,使之不能脫離對象存在。而在基于原型的面向?qū)ο蠓绞街校瑢ο髣t是依靠構(gòu)造器利用原型構(gòu)造出來的。 JavaScript 函數(shù)式腳本語言特性以及其看似隨意的編寫風(fēng)格,導(dǎo)致長期以來人們對這一門語言的誤解,即認(rèn)為 JavaScript 不是一門面向?qū)ο蟮恼Z言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽猓瑥膶φZ言感悟的角度闡述為什...
溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費(fèi)生命 這一切,源于阮大神博文學(xué)習(xí)Javascript閉包(Closure)- 阮一峰中的一道思考題 //問題1: var name = The Window; var object = { name : My Object, getNameFunc : function(){ return function(){ ...
閱讀 1458·2021-11-22 15:24
閱讀 2554·2021-10-11 11:06
閱讀 2359·2021-10-09 09:45
閱讀 2561·2021-09-09 09:33
閱讀 661·2019-08-30 15:53
閱讀 1471·2019-08-30 12:48
閱讀 746·2019-08-29 13:47
閱讀 529·2019-08-26 18:27