GetIdentifierReference
Return a value of type Reference whose base value is envRec, whose referenced name is name, and whose strict mode flag is strict.
我们看此处返回了一个 Reference , base value 是 envRec 也就是 10.3.1中传入的execution context’s LexicalEnvironment
(词法环境为环境记录项Environment Record的组成,它是规范用来管理当前作用域下面变量的类型,此处不用理解,知道它返回了这个东东就行了)
其抽象数据结构大概为:
foo_reference = {
"base": LexicalEnvironment,
"name": "foo",
"strict": false}
至此,第一步执行完毕,ref = foo_reference。
2. 因为是reference, 执行step 6:
Type(ref) is Reference
3. 因为是Environment Record,执行 step6.b:
Else, the base of ref is an Environment Record.
4. ImplicitThisValue
最后,thisValue等于执行ImplicitThisValue的结果,还是查看规范:
10.2.1.1.6 ImplicitThisValue()
Declarative Environment Records always return undefined as their ImplicitThisValue.
到此我们知道,foo()执行时, thisValue = http://www.netofthings.cn/JieJueFangAn/2016-09/undefined; 对应到 JavaScript 代码中的 this,还差最后一步:
Else if thisArg is null or undefined, set the ThisBinding to the global object.
真相大白:foo()执行时, this = global = window
如何解释 foo.bar()
1 . 执行函数调用规范中的step1:
Let ref be the result of evaluating MemberExpression.
foo.bar我们都知道是一个属性访问,那么执行属性访问的时候会发生什么呢? 答案都在规范中 :
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 等于执行 MemberExpression 在此处为 []左边的语句即 foo 的结果,上一节已经说过了 返回一个 reference .
2) baseValue 等于 GetValue(baseReference) 。
8.7.1 GetValue
* GetValue属于一个规范中比较重要的方法,此处为节约篇幅,暂时不讲,以后可以单开文章讲解。暂时记住他的结果一般为:如果是reference传入,会返回一个普通类型出来。比如 foo 为reference,通过GetValue之后就是一个普通的 object,也就是 foo 对应的 js 类型本身。
所以,baseValue = http://www.netofthings.cn/JieJueFangAn/2016-09/GetValue(baseReference) = GetValue(reference_foo) = foo
reference_foo_bar = {
"base": foo,
"name": "bar",
"strict": false}
2 因为是reference, 执行step 6:
Type(ref) is Reference
3. 因为是属性引用类型,执行step 6.a:
If IsPropertyReference(ref) is true, then
i.Let thisValue be GetBase(ref).
GetBase(ref) = reference_foo_bar.base = foo;
真相大白, foo.bar() 执行时 this 指向 foo
如何解释 (f = foo.bar)()
这个语句属于罕见写法,在各种经验总结中属于高级技巧,但是通过规范,一样分分钟搞定。
1 执行函数调用规范中step1:
Let ref be the result of evaluating MemberExpression.
f = foo.bar 是一个明显的赋值语句,我们查看规范,赋值语句会发生什么:
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.
可以看出简单赋值语句返回的是对等于号右边进行GetValue之后的结果,上一节讲了,foo.bar是一个属性访问的reference类型,而执行过GetValue之后的reference就会返回普通类型。
所以,rval = GetValue(rref) = GetValue(reference_foo_bar) = foo
2 ref不是reference,执行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)() 执行时 this = global = window
老司机的经验
虽然我们不是江湖郎中,但是每次查询规范也有点麻烦,此处还是有一定规律可循的。