3

使用 Babel 转译以下 es7 代码:

let obj = {
  @decorate
  prop: 10
}

let decorate = ( object, propertyName, desc ) => desc

decorate被调用时,属性描述符desc包含一个名为 的方法initializer,它返回obj.prop执行时的值。

initializer方法是 es7 装饰器规范的一部分,还是这纯粹是 Babel 转换为 es5 的副作用?

4

2 回答 2

2

es7 装饰器规范

请注意,既没有 ES7,也没有装饰器的规范。有一个关于如何扩展语言的草案,一个和谐提案。

decorate被调用时,属性描述符desc包含一个名为initializer

这有点奇怪。从目前的提案中,我预计装饰器总是使用该属性的属性描述符调用,这将是

{value: 10, writable: true, enumerable: true, configurable: true}

以你为例。但是,草案中的示例仅概述了类和对象字面量上的方法(和访问器属性)的装饰器,而不是值属性。

初始化方法是装饰器提案的一部分吗?

目前还没有,但他们的存储库中有一个INITIALIZER_INTEROP.md文件,其中概述了装饰器与PropertyInitialisers来自类属性提案的互操作性(这是一个未完成的草案,但也已经在 babel 中实现)。它确实使用了静态装饰器,这些装饰器被赋予带有initializer函数的描述符,该函数将被评估以在(之前)构造函数中初始化实例属性。

这纯粹是 Babel 转换为 es5 的副作用吗?

并不真地。IMO 这只是一个错误,可能源于 babel 如何转换类属性,这使得它们看起来与对象文字上的值属性相同。

于 2015-07-15T15:52:45.497 回答
1

如果您考虑proposal-class-fields TC39 提案,则该initializer功能最有意义。

考虑以下代码:

class C {
  prop = {};
}

const a = new C()
const b = new C()

console.log(a.prop === b.prop)

您会期望输出为false.

因此,属性的“值”不能存储为 static value,而是必须编码为每次都返回新值(此处为空对象)的函数。

该代码被转换为等效于:

class C {
    constructor () {
        const propName = 'prop'
        const propDesc = Object.getOwnPropertyDescriptor(this.constructor.prototype, propName)
        this[propName] = propDesc.initializer.call(this)
    }
}

这也允许您this在声明其他实例变量时引用(仍在该提案的上下文中):

class C {
    entries = [ 1, 2, 3 ];
    count = this.entries.length;
}

由于class C基本上是编写的语法糖C.prototype,类属性上的装饰器实际上与对象属性上的装饰器相同(在这种情况下,对象是原型)。

initializer模式允许在这两种情况下使用单一方式编写装饰器。

于 2019-06-17T08:41:13.447 回答