如何在JavaScript中正确子类化子类?

时间:2016-08-24 07:38:00

标签: javascript class inheritance

我认为我对如何在JavaScript中正确扩展类有了很好的理解,但是在扩展子类时,当我覆盖一个方法时,我会遇到无限循环,并从子类调用父方法。我做错了,或者你不应该在JavaScript中以这种方式进行子类化。

有人可以帮助教育我吗?



var Grand = function() {
	this.test();
};

Grand.prototype.constructor = Grand;

Grand.prototype.test = function() { 
	console.log( "Grand!")
};



var Parent = function() {
  this.supr.constructor.call( this );
};

Parent.prototype = Object.create( Grand.prototype );
Parent.prototype.constructor = Parent;
Parent.prototype.supr = Grand.prototype;

Parent.prototype.test = function() { 
	this.supr.test.call( this );
  console.log( "Parent!" );
};



var Child = function() {
  this.supr.constructor.call( this );
};

Child.prototype = Object.create( Parent.prototype );
Child.prototype.constructor = Child;
Child.prototype.supr = Parent.prototype;

Child.prototype.test = function() { 
	this.supr.test.call( this );
  console.log( "Child!" );
};



var g = new Grand(); // Outputs "Grand!"
var p = new Parent(); // Outputs "Grand!" "Parent!"
var c = new Child(); // Error: Endless Loop!




我希望控制台能够登录" Grand!"," Parent!"," Child!"当实例化一个新的Child()时,我会得到一个无限循环。

我来自ActionScript背景,因此在JavaScript中创建类仍然会让我产生一些曲线球。感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

我建议切换到es6。这种原型设计可能是一个真正的混乱,更难以跟踪。但是如果你在浏览器中需要这个,你应该将代码转换为es5 whit babel等。只要你有一个最新的版本,在Node env就可以了。一些最新的浏览器也支持它

class Grand {
    constructor() {
        this.test()
    }

    test() {
        console.log( "Grand!")
    }
}

class Parent extends Grand {
    test() {
        super.test()
        console.log( "Parent!" )
    }
}

class Child extends Parent {
    test() {
        super.test()
        console.log( "Child!" )
    }
}

let g = new Grand(); // Outputs "Grand!"
let p = new Parent(); // Outputs "Grand!" "Parent!"
let c = new Child(); // Outputs "Grand!" "Parent! "child!"

它不仅更具可读性,而且代码更少,更容易理解

答案 1 :(得分:0)

问题在于这段代码:

var Parent = function() { this.supr.constructor.call( this );
};

考虑执行此代码时会发生什么:

var c = new Child();

此处this是变量c,因此this.supr.constructor始终是父代的构造函数,因为这些代码行中的设置:

Child.prototype.supr = Parent.prototype;  // i.e. this.supr = Parent.prototype
Parent.prototype.constructor = Parent;  // i.e. this.supr.constructor = Parent

因此,当Child的构造函数调用this.supr.constructor.call( this );时,它执行Parent函数,父函数再次执行this.supr.constructor.call( this );,导致调用Parent函数再次,导致无限循环。

修复是按如下方式调用基类函数:

var Child = function() { Child.prototype.supr.constructor.call( this ); };

this post

中的更多详情