Making inheritance make sense with Object.create()

JavaScript itself is conflicted about its prototypal nature. In a prototypal system, objects inherit from objects. JavaScript, however, lacks an operator that performs that operation. Instead it has a new operator...Prototypal Inheritance in JavaScript, Douglas Crockford

The goal is to create a new object with a given prototype link. The status quo goes something like this:

function Person(name) {  
    this.name = name;
}

Person.prototype = { species: 'human' };

var finn = new Person('Finn');  
console.log(finn);          // { name: 'Finn' }  
console.log(finn.species);  // human

var fiona = new Person('Fiona');  
console.log(fiona);         // { name: 'Fiona' }  
console.log(fiona.species); // human  

See that fancy new operator? If you aren't already familiar with it, good luck understanding what's going on here. What does this refer to? What does Person() return? What is this prototype property that's added to Person and how is finn linked to it?

The pattern for creating objects with the new operator has always seemed really strange to me, like all the rules of JavaScript are suddenly suspended. A bunch of magic happens and poof—you've got yourself an object and somehow Person.prototype is its prototype. Wait, what? No wonder people are confused about prototypal inheritance—none of it is ever explicitly coded!

This indirection was intended to make the language seem more familiar to classically trained programmers, but failed to do that, as we can see from the very low opinion Java programmers have of JavaScript.Prototypal Inheritance in JavaScript, Douglas Crockford

The reality is that this paradigm sucks, and there's a better way to create objects with much less magic.

ECMAScript 5 (released in 2009) made Object.create() available as an alternative to the new syntax. You pass it any object (we'll call ours personProto) and it returns a new object with personProto as its prototype. The new confusion is no longer necessary; we can rename Person() to the more descriptive newPerson() and lose the this:

var personProto = { species: 'human' };

function newPerson(name) {  
    var person = Object.create(personProto);
    person.name = name;
    return person;
}

var finn = newPerson('Finn');  
console.log(finn);          // { name: 'Finn' }  
console.log(finn.species);  // human

var fiona = newPerson('Fiona');  
console.log(fiona);         // { name: 'Fiona' }  
console.log(fiona.species); // human  

Ah, suddenly it all makes sense! You define a function that when called creates an object with a specified prototype, assigns that object whatever properties you want, and finally returns it. It does the exact same thing as the first example, except without the hand-waving. This is essentially a native and better-looking implementation of Crockford's abstraction:

function object(o) {  
    function F() {}
    F.prototype = o;
    return new F();
}

It takes an old object as a parameter and returns an empty new object that inherits from the old one. If we attempt to obtain a member from the new object, and it lacks that key, then the old object will supply the member. Objects inherit from objects. What could be more object oriented than that?Prototypal Inheritance in JavaScript, Douglas Crockford

Browser compatibility is actually pretty great at this point. If you need to support legacy browsers, you can include an ES5 shim.

I don't know what this means for new, if it is going obsolete or if there's some important use-case I'm overlooking. The least you can say is that Object.create() is a good addition to the language, and a reaffirmation of JavaScript's simple, prototypal nature.