Inheritance in Javascript

Define Inheritance

Before I dive into Inheritance in Javascript, lets first define what I understand under inheritance.

  • Inheriting the implementation of an Object or Class
  • Being able to override the inherited implementation
  • Able to keep things private to the Object or Class
  • Able to keep things private, but still accessible for inheriting Objects or Classes
  • Able to access the super Object or Class

Lets see how this is done in javascript, with help of my own library EnoFJS!
(Link to EnoFJS)

Creating an Object or Class

The in my opinionĀ BAD way:

function Animal(){}
Animal.prototype = {
name: 'animal',
sayHello: function sayHello(){
return 'Hi, my name is ' + this.name + '!';
}
};
function Dog(){}
Dog.prototype = new Animal();
var dog = new Dog();
dog instanceof Animal; //True
dog.sayHello(); //Hi, my name is animal!
view raw gistfile1.js hosted with ❤ by GitHub

Why do I think this is a bad way of inheriting? Because all functions you put on the prototype, can only access public available properties and functions.

The way with EnoFJS:

var Animal = clazz(function Animal(){
this.private = {
name: 'animal'
};
this.public = {
sayHello: function sayHello(){
return 'Hi, my name is ' + this.private.name + '!';
}
};
});
var Dog = clazz(function Dog(){
this.extend = 'Animal';
});
var dog = new Dog();
dog instanceof Animal; //True
dog.sayHello(); //Hi, my name is animal!
dog.name; //undefined
view raw gistfile1.js hosted with ❤ by GitHub

Overriding, but keep things private to the parent

Continuing the BAD way:

function Animal(){}
Animal.prototype = {
name: 'animal',
sayHello: function sayHello(){
return 'Hi, my name is ' + this.name + '!';
}
};
function Dog(){}
Dog.prototype = new Animal();
Dog.prototype.sayHello = function sayHello(){
return 'Hello, my name is ' + this.name + '!';
};
var dog = new Dog();
dog instanceof Animal; //True
dog.sayHello(); //Hello, my name is animal!
view raw gistfile1.js hosted with ❤ by GitHub

Notice that the name is not private!

The way of EnoFJS:

var Animal = clazz(function Animal(){
this.private = {
name: 'animal'
};
this.public = {
sayHello: function sayHello(){
return 'Hi, my name is ' + this.private.name + '!';
}
};
});
var Dog = clazz(function Dog(){
this.extend = 'Animal';
this.public = {
sayHello: function sayHello(){
return 'Hello, my name is ' + this.private.name + '!';
}
};
});
var dog = new Dog();
dog instanceof Animal; //True
dog.sayHello(); //Hello, my name is undefined!
dog.name; //undefined
view raw gistfile1.js hosted with ❤ by GitHub

Notice that this.private.name is only accessible for the original and therefor is resolved as undefined for the dog!

Protected

As displayed above, the “common practices” for inheritance in javascript, don’t really handle privacy very well. However this doesn’t mean it is impossible to achieve this, which is shown with EnoFJS. An even more tricky concept for accessibility is the protected accessibility. Through the EnoFJS library it is made possible:

var Animal = clazz(function Animal(){
this.protected = {
name: 'animal'
};
this.public = {
sayHello: function sayHello(){
return 'Hi, my name is ' + this.protected.name + '!';
}
};
});
var Dog = clazz(function Dog(){
this.extend = 'Animal';
this.public = {
sayHello: function sayHello(){
return 'Hello, my name is ' + this.protected.name + '!';
}
};
});
var dog = new Dog();
dog instanceof Animal; //True
dog.sayHello(); //Hello, my name is animal!
dog.name; //undefined
view raw gistfile1.js hosted with ❤ by GitHub

Super and Constructor!

Something even more rare in the world of javascript, is the super access. Access to the method of the parent:

var Animal = clazz(function Animal(){
this.private = {
name: 'animal'
};
this.public = {
sayHello: function sayHello(){
return 'Hi, my name is ' + this.private.name + '!';
}
};
this.constructor = function constructor(name){
this.private.name = name;
};
});
var Dog = clazz(function Dog(){
this.extend = 'Animal';
this.public = {
sayHello: function sayHello(){
return this.super.sayHello() + ' How are you?';
}
};
this.constructor = function constructor(name){
this.super.constructor(name);
};
});
var dog = new Dog('Brian');
dog instanceof Animal; //True
dog.sayHello(); //Hello, my name is Brian! How are you?
dog.name; //undefined
view raw gistfile1.js hosted with ❤ by GitHub

After match

  • Inheriting the implementation of an Object or Class
    Easy achievable without a library
  • Being able to override the inherited implementation
    Achievable without library, but no private scoping
    With EnoFJS, it is achievable even with private scoping!
  • Able to keep things private to the Object or Class
    So far I’ve only seen it made possible with BackboneJS and EnoFJS
  • Able to keep things private, but still accessible for inheriting Objects or Classes
    Something I have only seen with EnoFJS
  • Able to access the super Object or Class
    Something I have only seen with EnoFJS

Conclusion

Javascript is so dynamic, it opens so many possibilities! With the help of a little library(less then 2kb), we are able to do full inheritance with private, protected and even super access!