如何在 Javascript 中调用祖父母 class 的 setter
How to call setter of grandparent class in Javascript
假设我有 3 个 classes Child
、Parent
和 Grandparent
,按如下层次结构连接:
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
//I know how to call Parent's setter of myField:
//super.myField = value;
//But how to call Grandparent's setter of myField here?
}
}
如何在 Child
class 的 setter 中调用 Grandparent
的 myField
的 setter?
我对 setter 特别感兴趣,而不是方法。此外,最好不要对 Grandparent
class 的 Parent
进行更改。
我不明白如何使用 super
因为它只引用 Parent
class 以及使用 Grandparent.prototype.<what?>.call(this, ...)
之类的东西因为我不知道不知道在原型中到底要调用什么。
有人对此案例有什么建议吗?
提前致谢!
您可能会找到一种方法来做到这一点,但您不应该这样做,尤其是在您进行 class-based OOP 时,因为它会破坏 class-based 模型。在任何理智的环境中,如果 Parent 实现 setX(),它期望 setX() 在其上下文中以其定义的方式运行。它不会覆盖 setX(),因此它可以按照以前的方式运行。
所以,如果您问这个问题,要么是您的 class 层次结构设计有误,要么您实际上需要 prototype-based OOP。
如果你写 Parent,我假设你试图获得的是对某个 属性 的无中介访问。方法是在 parent/gradpa 上定义一个方法,如 setXClean(),用作 celan setter。在这种情况下,您可能希望它在祖父母上受到保护和最终处理。
using something like Grandparent.prototype.<what?>.call(this, ...)
您的方向是正确的,您可以使用 Object.getOwnPropertyDescriptor
:
访问 setter 方法
Object.getOwnPropertyDescriptor(Grandparent.prototype, "myField").set.call(this, value);
虽然有一个更简单的方法:使用带有自定义接收器的 Reflect.set
helper:
Reflect.set(Grandparent.prototype, "myField", value, this);
这还有一个好处,就是当 Grandparent
没有定义 setter 时它仍然有效。
就是说,我同意@Dinu 的观点,您的 class 层次结构(或您的总体设计,也许您甚至不应该使用 classes 或继承)可能存在问题,当您需要这样做。
在我看来,最简单的方法是在祖父母 class 中创建另一个独特的 setter 或方法来设置 myField
.
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
set grandParent_myField(value) { this.myField = value }
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
this.grandParent_myField = value
}
}
另一种选择是将 super.myField
放入每个 setter 的正文中:
class Grandparent {
constructor() { this._myField = null }
set myField(value) {
this._myField = value
}
}
class Parent extends Grandparent {
set myField(value) {
super.myField = value
}
}
class Child extends Parent {
set myField(value) {
super.myField = value
}
}
您可以将 Reflect.set()
与可选的 receiver
参数一起使用,如下所示:
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
Reflect.set(Grandparent.prototype, 'myField', value, this);
}
}
new Child().myField = 'foo';
如果您没有明确引用 Grandparent.prototype
,您可以使用 Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(this)))
来代替,这显然不太可取。不过,您可以创建一个辅助函数:
function getPrototypeOf (target, level = 1) {
return level > 0 ? getPrototypeOf(Object.getPrototypeOf(target), level - 1) : target;
}
并使用 getPrototypeOf(this, 3)
代替 Grandparent.prototype
将原型链向上递归到祖父母:
function getPrototypeOf (target, level = 1) {
return level > 0 ? getPrototypeOf(Object.getPrototypeOf(target), level - 1) : target;
}
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
Reflect.set(getPrototypeOf(this, 3), 'myField', value, this);
}
}
new Child().myField = 'foo';
假设我有 3 个 classes Child
、Parent
和 Grandparent
,按如下层次结构连接:
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
//I know how to call Parent's setter of myField:
//super.myField = value;
//But how to call Grandparent's setter of myField here?
}
}
如何在 Child
class 的 setter 中调用 Grandparent
的 myField
的 setter?
我对 setter 特别感兴趣,而不是方法。此外,最好不要对 Grandparent
class 的 Parent
进行更改。
我不明白如何使用 super
因为它只引用 Parent
class 以及使用 Grandparent.prototype.<what?>.call(this, ...)
之类的东西因为我不知道不知道在原型中到底要调用什么。
有人对此案例有什么建议吗?
提前致谢!
您可能会找到一种方法来做到这一点,但您不应该这样做,尤其是在您进行 class-based OOP 时,因为它会破坏 class-based 模型。在任何理智的环境中,如果 Parent 实现 setX(),它期望 setX() 在其上下文中以其定义的方式运行。它不会覆盖 setX(),因此它可以按照以前的方式运行。
所以,如果您问这个问题,要么是您的 class 层次结构设计有误,要么您实际上需要 prototype-based OOP。
如果你写 Parent,我假设你试图获得的是对某个 属性 的无中介访问。方法是在 parent/gradpa 上定义一个方法,如 setXClean(),用作 celan setter。在这种情况下,您可能希望它在祖父母上受到保护和最终处理。
using something like
Grandparent.prototype.<what?>.call(this, ...)
您的方向是正确的,您可以使用 Object.getOwnPropertyDescriptor
:
Object.getOwnPropertyDescriptor(Grandparent.prototype, "myField").set.call(this, value);
虽然有一个更简单的方法:使用带有自定义接收器的 Reflect.set
helper:
Reflect.set(Grandparent.prototype, "myField", value, this);
这还有一个好处,就是当 Grandparent
没有定义 setter 时它仍然有效。
就是说,我同意@Dinu 的观点,您的 class 层次结构(或您的总体设计,也许您甚至不应该使用 classes 或继承)可能存在问题,当您需要这样做。
在我看来,最简单的方法是在祖父母 class 中创建另一个独特的 setter 或方法来设置 myField
.
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
set grandParent_myField(value) { this.myField = value }
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
this.grandParent_myField = value
}
}
另一种选择是将 super.myField
放入每个 setter 的正文中:
class Grandparent {
constructor() { this._myField = null }
set myField(value) {
this._myField = value
}
}
class Parent extends Grandparent {
set myField(value) {
super.myField = value
}
}
class Child extends Parent {
set myField(value) {
super.myField = value
}
}
您可以将 Reflect.set()
与可选的 receiver
参数一起使用,如下所示:
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
Reflect.set(Grandparent.prototype, 'myField', value, this);
}
}
new Child().myField = 'foo';
如果您没有明确引用 Grandparent.prototype
,您可以使用 Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(this)))
来代替,这显然不太可取。不过,您可以创建一个辅助函数:
function getPrototypeOf (target, level = 1) {
return level > 0 ? getPrototypeOf(Object.getPrototypeOf(target), level - 1) : target;
}
并使用 getPrototypeOf(this, 3)
代替 Grandparent.prototype
将原型链向上递归到祖父母:
function getPrototypeOf (target, level = 1) {
return level > 0 ? getPrototypeOf(Object.getPrototypeOf(target), level - 1) : target;
}
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
Reflect.set(getPrototypeOf(this, 3), 'myField', value, this);
}
}
new Child().myField = 'foo';