[ECMAScript] 当Public Class Fields是Arrow Function时this的指向

1. Babel

Public Class Fields目前是TC39 Stage 2的特性。

在实际项目中,我们使用了Babel进行转译。
Public Class Fields如果是一个箭头函数,那么这个函数中this的指向,如下所示。
(可在Babel REPL中试验

class A {
    v = this;  // instance

    static f = () => {
        return this;  // undefined
    }

    g = () => {
        return this;  // instance
    }
}

alert(A.f() === undefined);  // true

const a = new A;
alert(a.g() === a);  // true
alert(a.v === a);  // true

对于static字段,thisundefined
对于实例字段,this指向类的实例。


2. Public Class Fields

(1)ClassDefinitionEvaluation

我们看Public Class Fields规范,
执行过程是从ClassDefinitionEvaluation开始的,
这个函数比较长,我们只截取与public class fields有关的部分,如下,

因此在class声明的时候,对于那些public class fields进行了求值。
实际调用的是ClassPublicFieldDefinitionEvaluation函数,
该函数最后返回了一个Record


(2)ClassPublicFieldDefinitionEvaluation

其中[[initializer]]字段是一个函数,由FunctionCreate创建。
FunctionCreateECMAScript规范中定义的函数。

因此,每一个public class fields对应一个Record
这个Record中有一个[[initializer]]函数字段,
函数体是产生式PublicFieldDefinition: PropertyName Initializer中的Initializer
函数的求值结果是public class fields的值。

为什么不直接使用产生式中Initializer对应的值呢,
而是要先把它包裹成一个函数。
这是为了改变public class fields等式右边this指向。

class A {
    v = this;  // instance
}

到此为止,class声明时要做的事情就完成了,
然后我们要看实例化时发生的事情。


(3)[[Construct]]

这个函数描述了进行new操作时发生的事情,
其中,InitializePublicInstanceFields表示了对public class fields初始化,
OrdinaryCallEvaluateBody表示了求值classconstructor函数。

下面我们看InitializePublicInstanceFields函数。


(4)InitializePublicInstanceFields

这时拿到ClassPublicFieldDefinitionEvaluation返回的Record
获取它的[[initializer]]函数字段,然后用当前类的实例,调用它,
因此,this就指向当前类型的实例了。

class A {
    v = this;

    g = () => {
        return this;
    }
}

// 声明时,变成了
class A {
    v = new Record({
        [[initializer]]:function(){
            return this;
        }
    });

    g = new Record({
        [[initializer]]:function(){
            return ()=>{
                return this;
            }
        }
    });
}

// new的时候变成了
class A {
    v = record.[[initializer]].call(instance);

    g = record.[[initializer]].call(instance);
}

因此,public class fields字段中的this指向类的实例。


参考

Babel REPL - Stage 2
Public Class Fields
ECMAScript® 2017 Language Specification

material-ui中的例子
React官方文档中的例子 - handleClick

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 70,713评论 12 116
  • ----------------- *模型 模型是业务对象的呈现 * 系统已定义的模型查看 设置->技术->数据结...
    守望村夫阅读 1,326评论 0 1
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    会飞的鱼69阅读 21,060评论 18 385
  • Public Class Fields是目前处于Stage 2的ECMAScript特性,用于便捷的为class声...
    何幻阅读 1,025评论 0 2
  • 记录集 model的数据是通过数据集合的形式来使用的,定义在model里的函数执行时它们的self变量也是一个数据...
    玖零网络科技阅读 12,739评论 0 14