我在为length
我的 ES6 类扩展的属性提供静态 getter 函数时遇到问题。事实证明,实际的Function.length
getter 总是优先于我自己的实现。
class Foo {
static get value() {
return 'Foo';
}
static get length() {
return this.value.length;
}
}
class Bar extends Foo {
static get value() {
return `${super.value}Bar`;
}
}
console.log(Foo.value, Foo.length); // 'Foo', 3
console.log(Bar.value, Bar.length); // 'FooBar', 0
在上面的示例中,Foo
完全符合我的预期,Bar
而不是太多。Bar.value
确实回来了'FooBar'
,但让我Bar.length
感到0
惊讶。
我花了一段时间才意识到它的0
来源,正如我完全预期的那样(并且在某种程度上6
会理解)。3
事实证明,0
提供的值Bar.length
实际上是constructor
函数的长度Bar
,我在用 ES5 表示法编写相同的示例时意识到了这一点,但有一种快速的方法可以证明这一点;只需添加一个constructor
到Bar
.
class Bar extends Foo {
constructor(a, b, c, d) {
// four configured parameters
}
static get value() {
return `${super.value}Bar`;
}
}
console.log(Foo.value, Foo.length); // 'Foo', 3
console.log(Bar.value, Bar.length); // 'FooBar', 4
有办法解决这个问题:
- 添加
static get length()
到所有扩展(不是我的继承想法) - 使用不同的属性名称(例如
static get size()
按预期工作,但不是 JS 中常用的属性) length
从具有工作(例如class Foo extends Array {...}
)的内置类扩展基础-
如果有更合适的方法可以做到这一点,这些都不是我想做的。
所以我的问题是;有没有人知道一个正确的方法来拥有一个按预期继承的自定义属性覆盖,或者我太固执了?
如前所述,我通过将类语法编写为(我相信)将是 ES5 等价物来找出问题所在,因为它可能对其他开发人员有益,并且可能会阐明我认为ES6 类是如何工作的在这里。(如果有人对如何在 Stackoverflow 上使这个位可折叠有提示,请随时编辑/建议)
我想在 ES5 语法中发生了什么
我知道 ES6 类主要是围绕 JS 原型继承的语法糖,所以似乎发生的Bar
事情是这样的;
function Foo() {}
Object.defineProperties(Foo, {
value: {
configurable: true,
get: function() {
return 'Foo';
}
},
length: {
configurable: true,
get: function() {
return this.value.length;
}
}
});
function Bar() {}
Bar.prototype = Object.create(Object.getPrototypeOf(Foo));
Object.defineProperties(Bar, {
value: {
configurable: true,
get: function() {
return 'Bar' + Foo.value;
}
}
});
console.log(Foo.value, Foo.length); // 'Foo', 3
console.log(Bar.value, Bar.length); // 'FooBar', 0
我希望Foo
考虑到属性描述符,例如:
function Bar() {}
Bar.prototype = Object.create(Object.getPrototypeOf(Foo));
Object.defineProperties(Bar, Object.assign(
// inherit any custom descriptors
Object.getOwnPropertyDescriptors(Foo),
{
configurable: true,
value: {
get: function() {
return 'Bar' + Foo.value;
}
}
}
));
console.log(Foo.value, Foo.length); // 'foo', 3
console.log(Bar.value, Bar.length); // 'bar', 6