从 ES 范例 中明白 this

从 ES 范例 中邃晓 this

本认为对 JS 中的 this 已很熟练了,再看完冴羽的博客后,才发明本身对 ES 范例知之甚少,本来我都是依据履历在推断 this,这篇文章会从最底层的 ES 范例上去引见 this 的推断。

本文已同步到个人博客从 ES 范例 中邃晓 this,谢谢勉励。

一道测试题激发的思索

第一次做这道题时,只对了第一题。。

var value = 1;

var foo = {
  value: 2,
  bar: function() {
    return this.value;
  }
};

//示例1
console.log(foo.bar());
//示例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)());

先想一想这道题的答案,然后解释一下缘由。

范例文档

要完全弄邃晓上面的测试题,还得看范例文档 😂

罕见的几种范例:

  • Reference 范例
  • 函数挪用范例
  • 属性读取范例
  • 括号运算范例
  • 赋值运算范例
  • 逻辑与算法范例
  • 逗号运算范例

Reference 范例

在 ECMAScript 范例中另有一种只存在于范例中的范例,它们的作用是用来形貌言语底层行动逻辑。

  • 范例 8.7 The Reference Specification Type

    Reference 范例实例大抵长如许:

    var foo = {
      bar: function() {
        return this;
      }
    };
    var fooReference = {
      base: EnvironmentRecord,
      name: 'foo',
      strict: false
    };
    GetBase(fooReference); // EnvironmentRecord;
    
    var barReference = {
      base: 'foo',
      name: 'bar',
      strict: false
    };
    GetBase(barReference); // foo;
    • GetBase(V). Returns the base value component of the reference V.
    • HasPrimitiveBase(V). Returns true if the base value is a Boolean, String, or Number.
    • IsPropertyReference(V). Returns true if either the base value is an object or HasPrimitiveBase(V) is true; otherwise returns false.
  • 8.7.1 GetValue (V)

    • If Type(V) is not Reference, return V.
    • Let base be the result of calling GetBase(V).
  • 范例 10.2.1.1.6 ImplicitThisValue()

    • Return undefined.

函数挪用范例

  • 范例 11.2.3 Function Calls

    • 步骤1将 ref 赋值为 MemberExpression(简朴邃晓 MemberExpression 实在就是()左侧的部份)
    • 步骤2推断 ref 的范例

      • 步骤3假如 ref 是 Reference 范例

        • 步骤4假如 IsPropertyReference(ref) 是 true, 那末 this 的值为 GetBase(ref)
        • 步骤5假如 base value 值是 Environment Record, 那末 this 的值为 ImplicitThisValue(ref)
      • 步骤6假如 ref 不是 Reference 范例,那末 this 的值为 undefined

提醒

非严厉形式下,this 的值为 undefined 的时刻,其值会被隐式转换为全局对象。

示例 1 解答

1、运用属性读取范例:猎取 foo.bar 的返回范例。

2、交给函数挪用范例,去剖析 this。

  • 范例 11.2.1 Property Accessors

    • Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.
    • 因而可知,属性读取,默许返回一个 Reference 范例
  • 函数挪用范例

    • 步骤1 -> 步骤2 -> 步骤3 -> 步骤4

示例 2 解答

1、运用属性读取范例:猎取 foo.bar 的返回范例。

2、运用括号运算符范例:猎取 (foo.bar) 的返回范例。

3、交给函数挪用范例,去剖析 this。

  • 检察范例 11.1.6 The Grouping Operator

    • Return the result of evaluating Expression. This may be of type Reference.
    • 实际上 () 并没有对 MemberExpression 举行盘算,所以实在跟示例 1 的结果是一样的。
  • 函数挪用范例

    • 步骤1 -> 步骤2 -> 步骤3 -> 步骤4

示例 3 解答

1、运用赋值运算符范例:猎取 foo.bar = foo.bar 的返回范例。

2、运用括号运算符范例:猎取 (foo.bar = foo.bar) 的返回范例。

3、交给函数挪用范例,去剖析 this。

示例 4 解答

1、运用逻辑与算法范例:猎取 false || foo.bar 的返回范例。

2、运用括号运算符范例:猎取 (false || foo.bar) 的返回范例。

3、交给函数挪用范例,去剖析 this。

示例 5 解答

1、运用逗号操作符范例:猎取 foo.bar, foo.bar 的返回范例。

2、运用括号运算符范例:猎取 (foo.bar, foo.bar) 的返回范例。

3、交给函数挪用范例,去剖析 this。

一个最一般的状况

function foo() {
  console.log(this);
}

foo();

GetBase(fooReference); // EnvironmentRecord;

1、运用标识符剖析范例:猎取 foo 的返回范例。

2、交给函数挪用范例,去剖析 this。

  • 范例 10.3.1 Identifier Resolution

    • The result of evaluating an identifier is always a value of type Reference with its referenced name component equal to the Identifier String.
  • 函数挪用范例

    • 步骤1 -> 步骤2 -> 步骤3 -> 步骤5

总结

遇到题目时,只管从道理的角度对待题目,不要凭履历办事变,无妨多研讨研讨底层范例。

tip 参考资料

JavaScript 深切之从 ECMAScript 范例解读 this

ES5 范例文档

    原文作者:yhlben
    原文地址: https://segmentfault.com/a/1190000017103010
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞