JavaScript

[ECMAScript] 当Public Class Field

2017-03-17  本文已影响83人  何幻

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

上一篇下一篇

猜你喜欢

热点阅读