在尝试将 Java 应用程序移植到 JavaScript 时,我正在尝试以下继承技术:
var grandchild = new Grandchild();
Function.prototype.extend =
function(parent) {
var parentPrototype = parent.prototype;
this.prototype = Object.create(parentPrototype);
this.prototype.superPrototype = parentPrototype;
this.prototype.superConstructor = parent;
this.prototype.constructor = this;
}
;
function Parent(){
this.doStuff();
}
Parent.prototype.doStuff =
function() {
}
;
Child.extend(Parent);
function Child(){
this.superConstructor.call(this);
}
Child.prototype.doStuff = function() {
this.superPrototype.doStuff.call(this);
}
Grandchild.extend(Child);
function Grandchild(){
this.superConstructor.call(this);
}
Grandchild.prototype.doStuff = function() {
this.superPrototype.doStuff.call(this);
}
它适用于一级继承(即 var child = new Child()
),但使用 new Grandchild()
时,它会抛出 Uncaught RangeError: Maximum调用堆栈大小超出
,因为它陷入 function Child()
的无限递归。
- 到底发生了什么以及为什么?
- 如何调整此技术,以便它允许我调用
this.superConstructor.call(this)
和this.superPrototype.doStuff.call(this)
,如图所示不会对直接父级进行无限递归?
当我在调用中指定父类(super class)时,它会起作用,如下所示,但我不想这样做:
function Child(){
Parent.call(this);
}
Child.prototype.doStuff = function() {
Parent.prototype.doStuff.call(this);
}
function Grandchild(){
Child.call(this);
}
Grandchild.prototype.doStuff = function() {
Child.prototype.doStuff.call(this);
}
最佳答案
好的。事情是这样的:在 JS 中,this
和new
,在一起,是最容易混淆的一个概念。
当您调用new GrandChild()
时,什么是 this
?
this
是一个对象,其 __proto__
设置为指向的对象 GrandChild.prototype
。我们将此版本称为this
, gc_this
.
GrandChild()
现在执行this.superConstructor.call(this);
。我们也可以说它执行gc_this.superConstructor.call(gc_this);
,因为我们理论上重命名为 this
Grandchild()
内至gc_this
.
上面的执行调用Child()
与执行 new Child()
具有相同的效果。唯一的区别是,自从我们通过了gc_this
它不会返回任何内容以及任何和所有 this
Child()
内已替换为 gc_this
.
好的,到目前为止一切顺利。还没有问题。
但是现在开始出现问题:因为所有 this
Child()
内已替换为 gc_this
, Child()
内的代码已更改为:
function Child(){
gc_this.superConstructor.call(gc_this);
}
这与我们重命名时看到的完全相同行 this
GrandChild()
内至gc_this
.
因此,这最终会导致无限递归。
而在 JS 中实现多级经典继承的唯一方法就是直接使用静态类名,而不是依赖于动态设置的自定义属性。
<小时/>如果您想进一步了解该主题,我建议您查看:http://www.javascripttutorial.net/javascript-prototype/
关于JavaScript继承: Uncaught RangeError: Maximum call stack size exceeded,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29208803/