使用 Babel 转译以下 es7 代码:
let obj = {
@decorate
prop: 10
}
let decorate = ( object, propertyName, desc ) => desc
当decorate
被调用时,属性描述符desc
包含一个名为 的方法initializer
,它返回obj.prop
执行时的值。
该initializer
方法是 es7 装饰器规范的一部分,还是这纯粹是 Babel 转换为 es5 的副作用?
使用 Babel 转译以下 es7 代码:
let obj = {
@decorate
prop: 10
}
let decorate = ( object, propertyName, desc ) => desc
当decorate
被调用时,属性描述符desc
包含一个名为 的方法initializer
,它返回obj.prop
执行时的值。
该initializer
方法是 es7 装饰器规范的一部分,还是这纯粹是 Babel 转换为 es5 的副作用?
es7 装饰器规范
请注意,既没有 ES7,也没有装饰器的规范。有一个关于如何扩展语言的草案,一个和谐提案。
当
decorate
被调用时,属性描述符desc
包含一个名为initializer
这有点奇怪。从目前的提案中,我预计装饰器总是使用该属性的属性描述符调用,这将是
{value: 10, writable: true, enumerable: true, configurable: true}
以你为例。但是,草案中的示例仅概述了类和对象字面量上的方法(和访问器属性)的装饰器,而不是值属性。
初始化方法是装饰器提案的一部分吗?
目前还没有,但他们的存储库中有一个INITIALIZER_INTEROP.md文件,其中概述了装饰器与PropertyInitialisers
来自类属性提案的互操作性(这是一个未完成的草案,但也已经在 babel 中实现)。它确实使用了静态装饰器,这些装饰器被赋予带有initializer
函数的描述符,该函数将被评估以在(之前)构造函数中初始化实例属性。
这纯粹是 Babel 转换为 es5 的副作用吗?
并不真地。IMO 这只是一个错误,可能源于 babel 如何转换类属性,这使得它们看起来与对象文字上的值属性相同。
如果您考虑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
模式允许在这两种情况下使用单一方式编写装饰器。