隐藏 `this` - 词法名称解析

Shadowing `this` - lexical name resolution

编辑:我认为这不是重复的;它是一个隐藏参数,我想问一下与 this 相关的阴影和词法范围,阅读了 this SO Q/A re。阴影。

我认为名称 this 的含义可能会被动态解析(在范围界定方面),以解释为什么在我看来它没有被词法解析:

function foo() {return this;}
var a = {f: foo};
var b = {f: foo};

a.f() !== b.f();
a.f() !== foo();
a.f() !== window; //not strict mode

但后来我读到每个函数都默默地接收 this 作为附加参数。 (我意识到箭头函数是不同的。)

显然 helper() 没有像我们希望的那样工作:

ob = {
  meth: function(){
    var helper = function() {return this;};
    return helper();
  }
};
ob.meth(); //Window or undefined

据我所知,解释器不是通过查看封闭范围来解决 this(结果是 ob),而是用 [= 调用 helper() 12=] 设置为 undefined (严格模式),作为参数静默传递。

那么周围作用域的 this 是否实际上是 shadowed,因此词法作用域实际上在起作用?

你是对的。除了箭头函数, this 永远不会在词法上解析。它总是指以下之一:

  1. 调用函数的对象,例如valueOfThis.foo()
  2. applycall 的第一个参数,例如 foo.apply(valueOfThis, params)foo.call(valueOfThis, ...)
  3. DOM 元素,在事件处理程序的情况下,例如 <button onclick="alert(this.tagName.toLowerCase());"/>
  4. 正在构造的对象,当函数作为构造函数时,如Foo = function(){ ... }; new Foo()
  5. 绑定到函数的对象,如果函数是使用bind创建的,例如bar = function(){ ... this ...}; foo = bar.bind(valueOfThis); foo()
  6. 在getter/setter中,this指的是属性被访问或设置的对象,如valueOfThis.someProperty = 123
  7. window(通常)如果none以上情况,如foo()

@Bergi 在下面的评论中为所有这些提供了 great reference

绑定函数 的情况下,被调用的函数实际上是一个不同于传递给 bind 方法的函数,因为 bind方法创建一个新函数

So is the surrounding scope's this effectively being shadowed, hence lexical scoping is in fact in action?

是的,可以从那个角度来看。绑定到 helper 范围的 this 隐藏绑定到 meth 范围的那个。 (如果你使用了箭头函数,它就不会)。

不过,你还是要记住,this不是一个普通的变量,而是一个特殊的关键字。它只绑定到函数范围,它不可写,它在草率模式下有奇怪的强制对象语义,而且它总是隐式绑定——正如你所说,一个隐藏参数。

除非您试图了解 this 如何在箭头函数(及其词法解析)中工作,否则与作用域和阴影的类比是毫无用处的。