简体   繁体   中英

JavaScript Multi-level inheritance and isPrototypeOf

I have a multi-level inheritance implemented in JavaScript like below

function MovingObject(){

}

function Vehicle(){

}
Vehicle.prototype = Object.create(MovingObject);

function Car(){

}
Car.prototype = Object.create(Vehicle);

var c = new Car();

Car is child of Vehicle which in turn is child of MovingObject, so I am expecting Car to be indirect child of MovingObject.

Below statement returns true indicating Car is direct child of Vehicle

Vehicle.isPrototypeOf(c);

But, below statement does not return true

MovingObject.isPrototypeOf(c);

Any idea why it does not return true , and how to get it to return true ?

This is a common issue about JavaScript.

MovingObject or Vehicle are constructor functions but they're not the prototypes.

That is, you should derive using Object.create(ConstructorFunction.prototype) instead of just ConstructorFunction .

In JavaScript, even a function is an object and this is why Object.create(...) works when you provide a constructor function. The resulting object will have the constructor function object as prototype.

Actually you can both use the Object.create(ConstructorFunction.prototype) approach or you can achieve the same goal using new :

Vehicle.prototype = new MovingObject();

The main issue with new approach is that you're creating a new object using a constructor, and maybe you're adding unwanted data and behavior to the prototype:

 function MovingObject() { this.x = 11; } function Vehicle() {} Vehicle.prototype = new MovingObject(); var instance = Object.create(Vehicle.prototype); // What? instance has "x" property!! document.getElementById("result").textContent = instance.x;
 <div id="result"></div>

Update

OP said in some comment:

Does that mean we cannot establish a true is-a relationship between Car and MovingObject here? If yes, how can we test it using code? Meaning, I want to execute some code only if Car is-a Moving object. How can I achieve the test?

Check and execute the following code snippet to be more clear:

 function A() {} function B() {} B.prototype = Object.create(A.prototype); function C() {} C.prototype = Object.create(B.prototype); var instanceOfB = Object.create(B.prototype); var instanceOfC = Object.create(C.prototype); var result1 = A.prototype.isPrototypeOf(instanceOfC); var result2 = B.prototype.isPrototypeOf(instanceOfC); var result3 = A.prototype.isPrototypeOf(instanceOfB); document.getElementById("result1").textContent = result1; document.getElementById("result2").textContent = result2; document.getElementById("result3").textContent = result3;
 <h2>A is prototype of instanceOfC?</h2> <div id="result1"></div> <h2>B is prototype of instanceOfC?</h2> <div id="result2"></div> <h2>A is prototype of instanceOfB?</h2> <div id="result3"></div>

Update 2

As @RobertRossmann has commented out on this answer, same code snippet can be implemented using the instanceof operator, which has the added value of being valid to check if instances are of some prototype providing the constructor function:

 function A() {} function B() {} B.prototype = Object.create(A.prototype); function C() {} C.prototype = Object.create(B.prototype); var instanceOfB = Object.create(B.prototype); var instanceOfC = Object.create(C.prototype); var result1 = instanceOfC instanceof B; var result2 = instanceOfC instanceof C; var result3 = instanceOfB instanceof A; var result4 = instanceOfC instanceof A; document.getElementById("result1").textContent = result1; document.getElementById("result2").textContent = result2; document.getElementById("result3").textContent = result3; document.getElementById("result4").textContent = result4;
 <div id="result1"></div> <div id="result2"></div> <div id="result3"></div> <div id="result4"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM