GetIdentifierReference
Return a value of type Reference whose base value is envRec, whose referenced name is name, and whose strict mode flag is strict.
我們看此處返回了一個(gè) Reference , base value 是 envRec 也就是 10.3.1中傳入的execution context’s LexicalEnvironment
(詞法環(huán)境為環(huán)境記錄項(xiàng)Environment Record的組成,它是規(guī)范用來(lái)管理當(dāng)前作用域下面變量的類(lèi)型,此處不用理解,知道它返回了這個(gè)東東就行了)
其抽象數(shù)據(jù)結(jié)構(gòu)大概為:
foo_reference = {
"base": LexicalEnvironment,
"name": "foo",
"strict": false}
至此,第一步執(zhí)行完畢,ref = foo_reference。
2. 因?yàn)槭莚eference, 執(zhí)行step 6:
Type(ref) is Reference
3. 因?yàn)槭荅nvironment Record,執(zhí)行 step6.b:
Else, the base of ref is an Environment Record.
4. ImplicitThisValue
最后,thisValue等于執(zhí)行ImplicitThisValue的結(jié)果,還是查看規(guī)范:
10.2.1.1.6 ImplicitThisValue()
Declarative Environment Records always return undefined as their ImplicitThisValue.
到此我們知道,foo()執(zhí)行時(shí), thisValue = http://www.netofthings.cn/JieJueFangAn/2016-09/undefined; 對(duì)應(yīng)到 JavaScript 代碼中的 this,還差最后一步:
Else if thisArg is null or undefined, set the ThisBinding to the global object.
真相大白:foo()執(zhí)行時(shí), this = global = window
如何解釋 foo.bar()
1 . 執(zhí)行函數(shù)調(diào)用規(guī)范中的step1:
Let ref be the result of evaluating MemberExpression.
foo.bar我們都知道是一個(gè)屬性訪問(wèn),那么執(zhí)行屬性訪問(wèn)的時(shí)候會(huì)發(fā)生什么呢? 答案都在規(guī)范中 :
11.2.1 Property Accessors
The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:
1.Let baseReference be the result of evaluating MemberExpression.
2.Let baseValue be GetValue (baseReference)
8.Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict
1) baseReference 等于執(zhí)行 MemberExpression 在此處為 []左邊的語(yǔ)句即 foo 的結(jié)果,上一節(jié)已經(jīng)說(shuō)過(guò)了 返回一個(gè) reference .
2) baseValue 等于 GetValue(baseReference) 。
8.7.1 GetValue
* GetValue屬于一個(gè)規(guī)范中比較重要的方法,此處為節(jié)約篇幅,暫時(shí)不講,以后可以單開(kāi)文章講解。暫時(shí)記住他的結(jié)果一般為:如果是reference傳入,會(huì)返回一個(gè)普通類(lèi)型出來(lái)。比如 foo 為reference,通過(guò)GetValue之后就是一個(gè)普通的 object,也就是 foo 對(duì)應(yīng)的 js 類(lèi)型本身。
所以,baseValue = http://www.netofthings.cn/JieJueFangAn/2016-09/GetValue(baseReference) = GetValue(reference_foo) = foo
reference_foo_bar = {
"base": foo,
"name": "bar",
"strict": false}
2 因?yàn)槭莚eference, 執(zhí)行step 6:
Type(ref) is Reference
3. 因?yàn)槭菍傩砸妙?lèi)型,執(zhí)行step 6.a:
If IsPropertyReference(ref) is true, then
i.Let thisValue be GetBase(ref).
GetBase(ref) = reference_foo_bar.base = foo;
真相大白, foo.bar() 執(zhí)行時(shí) this 指向 foo
如何解釋 (f = foo.bar)()
這個(gè)語(yǔ)句屬于罕見(jiàn)寫(xiě)法,在各種經(jīng)驗(yàn)總結(jié)中屬于高級(jí)技巧,但是通過(guò)規(guī)范,一樣分分鐘搞定。
1 執(zhí)行函數(shù)調(diào)用規(guī)范中step1:
Let ref be the result of evaluating MemberExpression.
f = foo.bar 是一個(gè)明顯的賦值語(yǔ)句,我們查看規(guī)范,賦值語(yǔ)句會(huì)發(fā)生什么:
11.13.1 Simple Assignment ( = )
The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression is evaluated as follows:
Let rref be the result of evaluating AssignmentExpression.
Let rval be GetValue (rref)
Return rval.
可以看出簡(jiǎn)單賦值語(yǔ)句返回的是對(duì)等于號(hào)右邊進(jìn)行GetValue之后的結(jié)果,上一節(jié)講了,foo.bar是一個(gè)屬性訪問(wèn)的reference類(lèi)型,而執(zhí)行過(guò)GetValue之后的reference就會(huì)返回普通類(lèi)型。
所以,rval = GetValue(rref) = GetValue(reference_foo_bar) = foo
2 ref不是reference,執(zhí)行step7:
7.Else, Type(ref) is not Reference.
3 thisValue = http://www.netofthings.cn/JieJueFangAn/2016-09/undefined
同理:
Else if thisArg is null or undefined, set the ThisBinding to the global object.
真相大白, (f = foo.bar)() 執(zhí)行時(shí) this = global = window
老司機(jī)的經(jīng)驗(yàn)
雖然我們不是江湖郎中,但是每次查詢(xún)規(guī)范也有點(diǎn)麻煩,此處還是有一定規(guī)律可循的。