原型上具有默认属性的es6类在traceur中抛出

es6 class with default property on prototype throws in traceur

本文关键字:traceur 类在 es6 默认 属性 原型      更新时间:2023-09-26

我最近开始使用traceur,在原型上创建具有默认值的类时偶然发现了一个奇怪的行为。我想知道这是traceur中的一个bug,还是ES6类的预期行为?

class hasDefault {
  setValue ( v ) {
    this.v = v;
  }
}
Object.defineProperty( hasDefault.prototype, "v", {
  value : 5,
  enumerable : true
});
let a = new hasDefault;
console.assert(a.v === 5);
a.setValue(2);
console.assert(a.v === 2);

在traceur REPL 中运行

当我试图设置只读属性"v"时,它抛出了一个错误,我无法将其分配给它。这没有意义,因为该属性是在原型上定义的,而不是在实例上定义的。此外,我无法让Error在密封/冻结/不可扩展的对象上抛出es5,而且据我所知,Proxies并没有在V8中实现,所以……它最初是如何抛出错误的?这不是编译时的错误。

我的主要兴趣不是"让它发挥作用",这是微不足道的。您所需要做的就是用等效的Object.defineProperty替换this.v = v。我主要想知道它是否以及为什么会这样做,以及通过为原型分配默认属性而不是将它们存储在每个实例上,在这个数据结构中是否存在超过内存增益的负面性能影响。

当我试图设置只读属性"v"时,它抛出了一个错误,我无法将其分配给它。这没有意义,因为该属性是在原型上定义的,而不是在实例上定义的。

是的,该属性是只读的,因为writable属性默认为false。当继承v属性时,该属性对赋值也有效。

此外,我无法将该错误放入es5

你只需要使用严格模式,它就会做到:

"use strict";
var test = Object.create(Object.defineProperty({}, "v", {value: 5, enumerable: true}));
console.log(test.v) // 5
test.v = 1; // Unhandled Error: Invalid assignment in strict mode

如果使用仅指定value而不是getsetObject.defineProperty定义属性,则使用data descriptor(请参阅此处)。使用data descriptor可以添加writable属性来指定是否可以更改属性。默认情况下为writable=false

因此,如果只指定数据描述符的value,而不指定writable: true,则以后无法更改该属性。这种行为与ES6无关,因为Object.defineProperty是在ES5中引入的。

正确代码:

class hasDefault {
  setValue ( v ) {
    this.v = v;
  }
}
Object.defineProperty( hasDefault.prototype, "v", {
  value : 5,
  writable: true,
  enumerable : true
});
let a = new hasDefault;
console.assert(a.v === 5);
a.setValue(2);
console.assert(a.v === 2);

Traceur REPL