JavaScript继承:未捕获RangeError:超出最大调用堆栈大小

时间:2015-03-23 11:12:06

标签: javascript inheritance prototype prototypal-inheritance

在尝试将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 call stack size exceeded,因为它会在function Child()上无限递归。

  1. 究竟发生了什么以及为什么?
  2. 如何调整此技术,以便我可以调用this.superConstructor.call(this)this.superPrototype.doStuff.call(this),而无需在直接父级上进行无限递归?
  3. 当我在调用中指定超类时,它可以工作,但我不想这样做:

    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);
    }
    

1 个答案:

答案 0 :(得分:1)

好。事情就是这样:在JS中,SELECT * FROM firstTable WHERE EXISTS (SELECT TOP(1) 1 FROM secondTable WHERE firstTable.name = secondTable.name AND ( firstTable.age = secondTable.age OR (firstTable.age IS NULL AND secondTable.age IS NULL) ) ); this一起是最难掌握的概念。

当您致电new时,new GrandChild()是什么?

this是一个对象,其this设置为 __proto__指向的对象。我们将调用此版本的GrandChild.prototypethis

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()时看到的完全行。

因此,这最终会导致无限递归。

在JS中实现多级经典继承的唯一方法是直接使用静态类名,而不是依赖于动态设置的自定义属性。

如果您希望获得有关该主题的更多信息,我建议您可以查看:http://www.javascripttutorial.net/javascript-prototype/