前端面试-基础-JS(2)- this

132 阅读2分钟

面试系列原地址 gitee.com/gusiil/fein…,持续更新中

this

简单的理解

我们先简单的理解 this 指向: this 最终指向调用它的对象

var value = 1;

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

foo.bar() // 2

深入理解

如果我们用这个方法解释下以下的情况了

(foo.bar)() // 2
(foo.bar = foo.bar)() // 1
(false || foo.bar)() // 1
(foo.bar, foo.bar)() // 1

这种情况的加入,会让上述解释变得很牵强附会,这是因为上述解释本身就是片面的
我们从 ECMAScript 5 规范说起

Types

ECMAScript 规范将类型分为 语言类型规范类型

  • 语言类型是使用者使用的基本类型和引用类型

  • 规范类型是用来描述语言结构和语言类型的,即

    它们是为了更好地描述语言的底层行为逻辑才存在的
    但并不存在于实际的 js 代码中。

Reference

Reference 类型就是用来解释诸如 delete、typeof 以及赋值等操作行为的 规范类型 Reference 由三部分组成

  • base: 属性所处对象或者环境,this 所在
  • name: 属性名
  • strict: 是否是严格模式

而且规范中还提供了获取 Reference 组成部分的方法,比如 GetBase 和 IsPropertyReference。

  1. GetBase: 返回 base
  2. IsPropertyReference:如果 base value 是一个对象,就返回 true

确立 this 值

规范文本就不展开了,直接给结论

  1. 计算 MemberExpression 结果,赋值 ref
  2. 判断 ref 结果是不是一个 Reference 类型
    • 如果是
      2.1 IsPropertyReference(ref) 是 true,this 等于 GetBase(ref)
      2.2 IsPropertyReference(ref) 是 false,this 等于 ImplicitThisValue(ref)
    • 如果不是,this 为 undefined

ImplicitThisValue 方法始终返回 undefined

MemberExpression 它可以简单的理解为()左边的表达式

下面解释以上代码

(foo.bar)() // 2
// foo.bar 是Reference 但IsPropertyReference为false,它 的base是个环境记录,因此返回 undefined,非严格模式就是 window

(foo.bar = foo.bar)() // 1
// 有赋值操作符, 返回的值不是 Reference 类型

(false || foo.bar)() // 1
// 有逻辑符, 返回的值不是 Reference 类型

(foo.bar, foo.bar)() // 1
// 有逗号操作符,返回的值不是 Reference 类型

以上运算符本质上调用了 GetValue ,从 Reference 类型获取对应值的方法,因此都不会是 Reference

结语

简单的解释本质上是片面的,需要结合 Reference 规范类型,才能解释清楚 this 的具体指向