EXIT

EXIT

00:00:00

从ECMAScript规范中解读this指向

首先,ECMAScript的类型分为语言类型和规范类型.语言类型就是开发者可以直接使用的,而规范类型都是一些抽象出来的类型,用来描述语言底层行为逻辑.其中一种规范类型叫做Reference.它与this指向有密切关联.

Reference由三部分组成:

  • base value
  • referenced name
  • strict reference

base value 就是属性所在的对象,值只可能是 undefined, Object, Boolean, String, Number, EnvironmentRecord 其中的一种。

reference提供了两个方法:

  • GetBase:返回reference的base value(具体的值,非reference对象)
  • IsPropertyReference:如果base value是一个对象,则返回true

例如:

var foo = 1; //Reference fooReference = { base:EnvironmentRecord, name:'foo', strict:false, } GetValue(fooReference) // 1; /////// var foo = { bar: function () { return this; } }; foo.bar(); // bar对应的Reference是: var BarReference = { base: foo, propertyName: 'bar', strict: false }; IsPropertyReference(BarReference) //true

-> 那么如何确定this的值呢?

  • 计算 MemberExpression 的结果赋值给 ref

    如何计算MemberExpression?

    MemberExpression只可能是以下几种情况:

    原始表达式 | 函数定义表达式 | 属性访问表达式(a[b]) | 属性访问表达式(a.b) | 对象创建表达式

    例如:

    function foo() { console.log(this) } foo(); // MemberExpression 是 foo 函数定义表达式 function foo() { return function() { console.log(this) } } foo()(); // MemberExpression 是 foo() 函数定义表达式 var foo = { bar: function () { return this; } } foo.bar(); // MemberExpression 是 foo.bar 函数定义表达式
  • 判断 ref 是不是一个 Reference 类型

    • 如果 ref 是 Reference,并且 IsPropertyReference(ref) 是 true, 那么 this 的值为 GetBase(ref)
    • 如果 ref 是 Reference,并且 base value 值是 Environment Record, 那么this的值为 ImplicitThisValue(ref)
    • 如果 ref 不是 Reference,那么 this 的值为 undefined
var value = 1; var foo = { value: 2, bar: function () { return this.value; } } //示例1 console.log(foo.bar()); //foo.bar是一个Reference: // barReference:{ // base:foo, // propertyname:'bar', // strict:false, // } //并且 IsPropertyReference(ref) = true // getBase(ref) = foo = this //示例2 console.log((foo.bar)()); //示例3 console.log((foo.bar = foo.bar)()); //示例4 console.log((false || foo.bar)()); //示例5 console.log((foo.bar, foo.bar)());

看示例2:

console.log((foo.bar)());

foo.bar 被 () 包住, 实际上 () 并没有对 MemberExpression 进行计算,所以其实跟示例 1 的结果是一样的。

看示例3,有赋值操作符,所以返回的值不是 Reference 类型,

按照之前讲的判断逻辑:

2.3 如果 ref 不是Reference,那么 this 的值为 undefined

this 为 undefined,非严格模式下,this 的值为 undefined 的时候,其值会被隐式转换为全局对象。

看示例4,逻辑与算法,同上

看示例5,逗号操作符,同上

uid:lruMcF
VOIDIS.ME
  1. no-like
  2. message
  3. Bilibili
  4. Github
  5. RSS
  6. sun