ES6访问子类';在javascript中重写函数时使用“this”
我有以下代码:ES6访问子类';在javascript中重写函数时使用“this”,javascript,ecmascript-6,Javascript,Ecmascript 6,我有以下代码: class BaseClass { constructor() { // BELOW LINE CALLS OVERRIDDEN FUNCTION BUT WITH `this` OF BaseClass this.preHook(); } // THIS FUNCTION IS BEING OVERRIDDEN IN CHILD CLASS preHook(data) { return data; } } class Child
class BaseClass {
constructor() {
// BELOW LINE CALLS OVERRIDDEN FUNCTION BUT WITH `this` OF BaseClass
this.preHook();
}
// THIS FUNCTION IS BEING OVERRIDDEN IN CHILD CLASS
preHook(data) {
return data;
}
}
class ChildClass extends BaseClass {
constructor() {
super();
this.someKey = 'someValueFromChild';
}
preHook(data) {
console.log('this.someKey', this.someKey); //IT PRINTS undefined
}
}
var c = new ChildClass();
OUTPUT:
this.someKey undefined
Expecting
this.someKey someValueFromChild
因此,在基类的构造函数中,我调用了一个函数this.preHook(),该函数在ChildClass中被重写,当我们初始化ChildClass时,它调用基类的构造函数,然后调用this.preHook的重写版本,而不是打印在ChildClass中定义的someValueFromChild
,它正在打印未定义的内容(它使用父类的而不是子类的)
如何使用子类的此
如何使用子类的此
没有子类的“this
”。只有一个对象(由其原型对象支持)。基类中的this
和子类中的this
都指同一个对象
访问this.someKey
会导致该代码中的未定义,原因是子构造函数直到父构造函数完成后才设置someKey
,并且父构造函数调用preHook
,因此在子构造函数设置之前调用preHook
someKey
。因此,当preHook
尝试从对象读取它时,根本就没有someKey
属性。如果使用调试器逐步执行代码,您会看到这一点。下面是一个注释版本,显示了在以下情况下发生的情况:
类基类{
构造函数(){
log(“基类构造函数启动”);
这个;
log(“基类构造函数完成”);
}
//正在子类中重写此函数
预读(数据){
log(“调用BaseClass.preHook”);
返回数据;
}
}
类ChildClass扩展了基类{
构造函数(){
log(“子类构造函数启动”);
超级();
log(“ChildClass构造函数设置'someKey`”);
this.someKey='someValueFromChild';
log(“子类构造函数完成”);
}
预读(数据){
log(“调用ChildClass.preHook”);
log('this.someKey',this.someKey);
}
}
var c=new ChildClass();
。作为控制台包装器{
最大高度:100%!重要;
}
如何使用子类的此
没有子类的“this
”。只有一个对象(由其原型对象支持)。基类中的this
和子类中的this
都指同一个对象
访问this.someKey
会导致该代码中的未定义,原因是子构造函数直到父构造函数完成后才设置someKey
,并且父构造函数调用preHook
,因此在子构造函数设置之前调用preHook
someKey
。因此,当preHook
尝试从对象读取它时,根本就没有someKey
属性。如果使用调试器逐步执行代码,您会看到这一点。下面是一个注释版本,显示了在以下情况下发生的情况:
类基类{
构造函数(){
log(“基类构造函数启动”);
这个;
log(“基类构造函数完成”);
}
//正在子类中重写此函数
预读(数据){
log(“调用BaseClass.preHook”);
返回数据;
}
}
类ChildClass扩展了基类{
构造函数(){
log(“子类构造函数启动”);
超级();
log(“ChildClass构造函数设置'someKey`”);
this.someKey='someValueFromChild';
log(“子类构造函数完成”);
}
预读(数据){
log(“调用ChildClass.preHook”);
log('this.someKey',this.someKey);
}
}
var c=new ChildClass();
。作为控制台包装器{
最大高度:100%!重要;
}存在一种竞争条件,即ES6类的自然限制的结果。此
应始终出现在子构造函数中的super()
之后。因为此.preHook()
在父构造函数中调用(super
),无法在构造函数中分配this.someKey
并在this.preHook()调用期间显示
否则,this.preHook()
调用应该只在子构造函数中发生,这违背了钩子的概念,并阻止了子类的正确扩展
为了避免竞争条件,应该在类原型上定义someKey
,因此super
和这个
优先级不再是问题:
class ChildClass extends BaseClass {
constructor() {
super();
}
get someKey() {
return 'someValueFromChild';
}
...
}
允许维护适当类生命周期的另一种方法是在应用程序级别实现钩子,就像在JS框架中通常做的那样。可钩子类应该通过特定接口实例化,而不是直接实例化,即:
function instantiateWithHooks(cls, args) {
const instance = new cls(...args);
instance.preHook();
return instance;
}
正如另一个答案中所解释的,当实例化子类时,只有一个this
,它(通常)是子类的实例。存在一个竞争条件,即ES6类的自然限制的结果。this
应该总是出现在super()之后
在子构造函数中。由于在父构造函数(super
)中调用了this.preHook()
),因此无法在构造函数中分配this.preHook()
并在此.preHook()调用期间显示
否则,this.preHook()
调用应该只在子构造函数中发生,这违背了钩子的概念,并阻止了子类的正确扩展
为了避免竞争条件,应该在类原型上定义someKey
,因此<