As the other commenters and the articles they've linked already suggested, differential inheritance is "just" the normal, known prototypical inheritance.
Yet by using the term differential inheritance you focus on a more pure pattern than it is known in JavaScript (though quite common in other prototypical languages like Self, NewtonScript or Io). Unlike the pseudo-classical pattern, there are no constructors with new
usage at all. Instead, by using Object.create
you create a new object inheriting from the target object in one step, and then you create the necessary instance properties (only those that are different) manually (not with a constructor). It's not unusual to inherit from an object that you would consider to be an instance otherwise, instead of from a dedicated prototype object.
var object = Object.prototype;
// a Person constructor and a Person.prototype method would be more familiar
var person = Object.create(object);
person.greet = function() {
console.log("Hi, I'm "+this.firstName+" "+this.lastName);
};
// as would new Person("John", "Doe");
var jo = Object.create(person);
jo.firstName = "John";
jo.lastName = "Doe";
// but what now? We stay with "simple" Object.create here
var ja = Object.create(jo);
ja.firstName = "Jane";
jo.greet();
ja.greet();
As you can see creating a Jane is simple, but we would have to break with the new Constructor()
pattern if we had used it. That's why some JS gurus are advocating to use the pure pattern everywhere (so that you understand better what's going on) and are happy to have been given Object.create
with EcmaScript 5.
Still, using the constructor pattern and building conventional class hierarchies is common and helpful, and indeed possible in prototypical languages. Io for example will call an init
method (if existing) everytime you clone
an object, and in above example we could have used one as well which would have made the initialisation of Joe simpler:
person.init = function(f, l) {
this.firstName = f; this.lastName = l; return this;
}
var jo = Object.create(person).init("John", "Doe");
There is definitely no straight line to distinguish between differential and prototypical inheritance.