为什么箭头函数作为静态成员值不在词法范围内?

问题描述

class Foo {
  static v = 123;

  static bar = () => this.v;
}

console.log(Foo.bar());

我希望这段代码返回undefined,因为箭头函数是按词法作用域划分的,因此必须this急切地绑定到外部作用域。

但是,它返回123

为什么会这样?

是的,我知道它仍然是第3阶段,但是-提议的标准为何如此表现? (有关另一个示例,请参见https://babeljs.io/docs/en/babel-plugin-transform-class-properties。)

解决方法

tl; dr:每个类字段(无论是否静态)都在内部包装在一个方法中,该方法在某个时刻被相应的接收方(类或实例)调用。


因此,我不确定其中一些细节*,但基本上会发生这种情况:

对于每个带有初始化程序的字段(静态或非静态),都会创建一个函数/方法,并将初始化程序作为其主体。所以这个

static foo = () => this.v;

内部成为某物

function () { () => this.v }

那是在步骤28的the proposal中,最终导致了ClassFieldDefinitionEvaluation in this spec。该方法在步骤3.e中创建。

然后获取静态字段(现在是方法),并以类对象本身作为 receiver 进行调用(即,将中间方法内的this值设置为类对象) )。这发生在步骤34.a中,导致到DefineField in this spec。最后,将返回值(在您的情况下为箭头函数)用作实际属性的值。

用代码表示,大致是这样:

class Foo {}

Foo.v = function() { return 123; }.call(Foo);
Foo.bar = function() { return () => this.v; }.call(Foo);

*:我还不清楚中间方法如何返回值,但是可能有些东西说返回了函数体的最后一个表达式。