I'm trying to get my head fully wrapped around prototypal inheritance and Javascript's inheritance system.
I'm trying to figure out what the difference would be between these two examples. I'm going to guess that it has to do with the prototype inheritance chain, but I'm having trouble finding information relating the two.
function Vehicle(wheels) {
this.wheels = wheels;
}
function Car(doors) {
this.doors = doors;
Vehicle.call(this,4);
}
function Vehicle(wheels) {
this.wheels = wheels;
}
function Car(doors) {
this.doors = doors;
}
Car.prototype = new Vehicle(4);
In the first example you're initializing your Car object to have all the same properties of a new Vehicle object. However, it's not "real" inheritance, in the following ways:
var car = new Car(2);
car instanceof Vehicle; // => false
That's the first thing: instanceof won't work. Here's the second:
var car = new Car(2);
Vehicle.prototype.drive = function() {
console.log('vroom!');
};
car.drive(); // throws
So that's the second thing: accesses to a Car instance won't reach up the prototype chain to Vehicle's prototype.
With that in mind, I'd tend to favor the second approach.
That said, you might actually want to do both, as there could be per-instance initialization logic in your Vehicle constructor that you actually want to execute when you initialize a Car (and that won't happen just by setting the prototype).
To understand what I mean: in your examples you're always passing 4 as the wheels parameter to the Vehicle constructor, which makes sense. But suppose we add another parameter that can vary by instance:
function Vehicle(wheels, color) {
this.wheels = wheels;
this.color = color;
}
Now there are two approaches we could take here:
function Car(doors, color) {
this.doors = doors;
Vehicle.call(this, 4, color);
}
Car.prototype = new Vehicle();
Notice here that rather than pass anything to the Vehicle constructor when setting Car's prototype, we actually call the constructor explicitly in Car. This way we get color set properly.
The other approach would be:
function Car(doors, color) {
this.doors = doors;
this.color = color;
}
Car.prototype = new Vehicle(4, null);
That would work too.
The interpreter adds an internal reference (you can call proto if you will) that points to the prototype of the corresponding constructor.
If you run the first example and instantiate two instances of each constructor you will end up having something like the following:

Things that you need to notice here are:
carsObj has one additional property that the Car constructor doesn't define. The reason for the is this line Vehicle.call(this,4); that you have inside the Car constructor.The last bullet point is what restricts up from applying proper inheritance.
Similarly if you run the second example the memory might look like this:

The difference is quite evident. The prototype property of the Car constructor points to an instance of the Vehicle constructor, and so do all the instances of the Car constructor. This is due to this line Car.prototype = new Vehicle(4);.
This structure allows the instances of the Car constructor to access all the properties that are defined on the prototype of the parent class. This is due to how JavaScript traverses th prototype chained when looking for a property.
The shortcoming of this technique is that the Car instances do not inherit any instance properties from the Vehicle constructor. It inherits only the shared members.
A better solution is the combination of the above two techniques; That is:
function Vehicle(wheels) {
this.wheels = wheels;
}
function Car(doors) {
this.doors = doors;
Vehicle.call(this, 4)
}
Car.prototype = Object.create(Vehicle);
This way instances of the Car constructor will inherit both the shared and the instance members.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With