JavaScript继承: Uncaught RangeError: Maximum call stack size exceeded

标签 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调用堆栈大小超出,因为它陷入 function Child() 的无限递归。

  1. 到底发生了什么以及为什么?
  2. 如何调整此技术,以便它允许我调用 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 中,thisnew ,在一起,是最容易混淆的一个概念。

当您调用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_thisChild() 内的代码已更改为:

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/

相关文章:

JavaScript:DOM 文本节点

c++ - 派生类函数

javascript - 避免在外部调用原型(prototype)方法时丢失对象实例

javascript - 使 JavaScript 私有(private)方法可供其公共(public)方法访问

javascript - Javascript constructor 属性的意义是什么?

javascript - 根据页眉和页脚高度改变高度的动态内容

javascript - 创建或更新记录后,客户端(javascript 应用程序)是否应该请求 GET 列表?

javascript - 谷歌跨源请求

c++ - 如果 'C' 公开继承自 'B',B 私自继承自 'A',为什么我不能在 'A' 内部创建 'C' 的对象?

c# - 依赖注入(inject)的 Xamarin iOS Controller 自定义继承问题