Newcomers to JavaScript often misunderstand its object oriented style. Inheritance, in particular, seems foreign to people coming from other object oriented languages like C++ or Java. When I was new to JavaScript, I tried to manipulate the language to fit the style I already knew. But there's a better way. In this short tutorial I'll explain how JavaScript implements object inheritance and how you can use it to your advantage.
A Different Style
C++ and Java are class-based languages. In class-based languages, a class represents a data type—a blueprint for creating objects. Nothing is physically created until the "new" operator is used.
JavaScript is a prototypal language. There are no classes; no blueprints. Instead, we create an object immediately with the essential features and use it as a model—a prototype—for other objects.
The function above will be called to initialize new objects. But something else has happened behind the scenes. A new object has been created: Person.prototype
. It's from this prototype object that all new Person
objects will inherit.
Let's add some functions and properties to be shared among every new Person
object.
Now let's initialize two new Person
objects.
The object structure we get looks like this: diagram 1.
When we access a property in jane
or in noName
or in any other new Person
object, JavaScript will check in that object first. If the property exists, then JavaScript will return its value. If the property isn't found, then JavaScript will follow the inheritance chain and check for that property in the next object.
So when we access jane.name
, JavaScript will check the jane
object for the property name
and find the value "Jane Smith." When we access noName.name
, JavaScript will check the noName
object for the property name
. Since it doesn't exist there, JavaScript will follow the inheritance chain to Person.prototype
and find the value "John Doe."
Extending Objects
Next, let's look at how to extend objects into more specific kinds. I'm going to show you two ways of doing it. The first way is more common and perhaps simpler to understand. The second is a newer technique introduced by Douglas Crockford, a Senior JavaScript Architect at Yahoo!.
As before, we start with a function.
And, as before, a new object has been created—Employee.prototype
—from which all new Employee
objects will inherit. Now let's set Employee
to inherit from Person
.
New Employee
objects will inherit from Employee.prototype
, and Employee.prototype
now inherits from Person.prototype
.
Let's add some functions to be shared among every new Employee
object.
Now our object structure looks like this: diagram 2.
Let's give our new Employee
prototype a try.
Success! And finally our object structure looks like this: diagram 3.
Using Douglas Crockford's Technique
Now we'll take a look at Douglas Crockford's newer technique for extending objects. But first, let me show why a different technique was needed.
You may have noticed when we set Employee
to inherit from Person
that we initialized a nameless, ageless person. But what if the Person
function forbade the name from being blank?
Now our inheritance technique—initializing a nameless, ageless person—throws an error and kills the whole script. We need a way for Employee
to inherit from Person
without calling new Person()
. So Crockford wrote a method that produces a blank object that inherits from a given parent object.
Here's the custom method.
It's simple enough to start using this.
And that's it. Now Employee.prototype
inherits from Person.prototype
without unnecessarily executing the Person
function, and our script is happy again.
Original: March 12, 2009