admin管理员组

文章数量:1401772

I thought I had a good understanding on how to properly extend classes in JavaScript, but when extending a subclass I run into an endless loop when I override a method, and the call the parent method from the child class. I'm either doing it wrong, or you just shouldn't subclass this way in JavaScript.

Can anybody help educate me please?

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!

I thought I had a good understanding on how to properly extend classes in JavaScript, but when extending a subclass I run into an endless loop when I override a method, and the call the parent method from the child class. I'm either doing it wrong, or you just shouldn't subclass this way in JavaScript.

Can anybody help educate me please?

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!

I would expect the console to log "Grand!", "Parent!", "Child!" when instantiated a new Child(), but instead I get an endless loop.

I'm ing from an ActionScript background, so creating classes in JavaScript still throws me some curve balls. Thanks for the help in advance!

Share Improve this question asked Aug 24, 2016 at 7:37 SpaceCowboy2071SpaceCowboy2071 1,1551 gold badge13 silver badges20 bronze badges 1
  • 1 There is no really a concept of Class and Subclass in JavaScript (apart of sugar syntax in ES6). JavaScript is prototype base. – GibboK Commented Aug 24, 2016 at 7:40
Add a ment  | 

2 Answers 2

Reset to default 4

I remend switching to es6. This prototyping can be a real mess and is harder to keep track of. But then if you need this in the browser, you should transpile your code to es5 with babel or such. In the Node env, it's fine without as long as you have a recent up-to-date version. Some of the latest browser supports it as well.

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!"

Not only is it more readable, but it's less code and more understandable.

The problem is with this bit of code:

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

Consider what happens when this code executes:

var c = new Child();

Here this is the variable c, so this.supr.constructor will always be the parent's constructor as setup in these lines of code:

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

So, when the Child's constructor invokes this.supr.constructor.call( this ); it executes the Parent function, and the parent function again executes this.supr.constructor.call( this ); resulting the Parent function being invoked again, causing the endless loop.

A fix is to invoke base class functions as follows:

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

More details in this post

本文标签: classHow to properly subclass a subclass in JavaScriptStack Overflow