Skip to content Skip to sidebar Skip to footer

Javascript Prototypical Inheritance Confused

given the standard way of achieving inheritance like this function BaseClass() { } function SubClass() { BaseClass.call(this); } SubClass.prototype = Object.create(BaseClass

Solution 1:

Assigning values to things in JavaScript really just copies a reference (unless working with primitive types). So when you do this:

Subclass.prototype = BaseClass.prototype;

What you're really doing is assigning the prototype of SubClass to the same location in memory as the prototype of BaseClass, therefore any prototype related changes you make to SubClass will also affect BaseClass. Here's a little example:

functionBaseClass() {

}

functionSubClass() {
    BaseClass.call(this);
}

SubClass.prototype = BaseClass.prototype;
SubClass.prototype.constructor = SubClass;

SubClass.prototype.subClassFunction = function(){
    console.log("Added this to SubClass");
}

var baseObj = newBaseClass();
baseObj.subClassFunction(); // => "Added this to SubClass"

That's why you want to use

SubClass.prototype = Object.create(BaseClass.prototype);

because it will create a new and unique object with the specified prototype instead.

You can read more about how this function works here.

Solution 2:

Object Reference!

Say BaseClass has a method toString:

BaseClass.prototype.toString = function() {
  return'foo'
}

But you redefine the toString method in SubClass:

SubClass.prototype.toString = function() {
  return'bar'
}

You'll expect:

var b = new BaseClass(), s = new SubClass()
b.toString() //=> 'foo'
s.toString() //=> 'bar'

But if you use assignment to create inheritance what you will get is:

var b = new BaseClass(), s = new SubClass()
b.toString() //=> 'bar'
s.toString() //=> 'bar'

Because BaseClass.prototype and SubClass.prototype now reference the same object

Solution 3:

Inheritance, the __proto__:

When an object SubClass inherits from another object BaseClass, in JavaScript that means that there is a special property SubClass.__proto__ = BaseClass.

Code :

functionBaseClass() {
}

functionSubClass() {
}

varBaseClass = newBaseClass();
varSubClass = newSubClass();

BaseClass.a = 5;
SubClass.b = 10;

SubClass.__proto__ = BaseClass;

console.log(SubClass);

Output :

Here, BaseClass is inherited by SubClass and BaseClass variable is accessable through the SubClass.

enter image description here

Solution 4:

The syntax of JavaScript can be somewhat confusing. In JS, there isn't class inheritance but instance-based inheritance. An instance's parent is also called its prototype.

When you write instance.something or instance['something'], the JS engine looks at the instance to see if it has a member called something. If it doesn't, then it looks at the instance's prototype. If that object doesn't have the member something, it looks at the prototype's prototype, again and again until it finds the property or reaches an instance which inherits from null. In that case it will simply return undefined.

Functions have a special property called prototype which is something else. The function's .prototype is a simple object that has a constructor property which refers back to the function itself. When you create an object with the new keyword, that object's prototype will be set to the function's .prototype property. This is where the confusion comes from: the .prototype property of a constructor can be seen as the default prototype of all instances made with said constructor.

So when you add methods to a class by writing something like this:

MyClass.prototype.foo = function() {
  alert('foo');
};

...you're actually storing the function in the prototype of all MyClass instances. When the JS engine looks at the instances of MyClass, it will look for the foo member which it won't find. Then it will look at the instance's prototype which happens to be set to MyClass.prototype and it will find the foo member and fetch it.

It's important to make the difference between an instance's prototype and a function's .prototype, but most people don't realize it. When they speak of a class's prototype, they're talking about MyClass.prototype. The instance prototype is accessible via __proto__ in many browsers, but that's not a standard feature of JavaScript and shouldn't be used in your code.

Now let's look at the code you're using to simulate class inheritance.

SubClass.prototype = Object.create(BaseClass.prototype);SubClass.prototype.constructor = SubClass;

Object.create(parent) can be seen as a function that does this:

return {
  __proto__ : parent
};

In other words, it creates a blank Object whose prototype is the passed object. Since all SubClass instances will inherit from Subclass.prototype, replacing SubClass.prototype with an object that inherits from BaseClass.prototype makes sure all SubClass instances also inherit from BaseClass.

Sample MyClass.prototype console inspection

However, as I said earlier, the default .prototype attribute of a function is an empty object whose .constructor is set to the function itself. So by manually setting the .constructor again, we're perfectly mimicking default prototype behavior. If we don't do that, then instance.constructor will return the first defined .constructor property down the prototype chain, which will be BaseClass. It doesn't really change anything in terms of behavior unless our code actually depends on the constructor property, but it's safer to have it.

As a final note, like others mentioned before I could finally post this answer, you can't just do SubClass.prototype = BaseClass.prototype; because then you wouldn't be able to add methods to the SubClass without adding them to the BaseClass.

Post a Comment for "Javascript Prototypical Inheritance Confused"