18 May 2014
In this post we’ll talk about prototypes and we can use them to write code in a more familiar object-oriented way.
The basic way to create an object is:
There is a special object already defined called
Object. One of its properties is
getOwnPropertyNames, which is a function that takes an object and returns an array containing the name of properties defined in that object:
Note that it returns
getOwnPropertyNames, since it’s a property. Another interesting property returned is
prototype, which is an object.
All objects will inherit the properties in the
prototype object. Let’s see which properties are there:
Let’s take a look on the properties of a regular object:
It won’t list the properties inherited from
getOwnPropertyNames, as the name suggests, only lists properties defined at that object, not those inherited. But we can verify it exists by doing:
We can override the properties inherited
We can also add more properties to
Object.prototype so it’s available to all other objects:
Observe that even though we added the
custom property after creating object
a, the method
a.custom() exists is available. This is because when resolving the property from its name it first tries to look if the property is defined in the object itself, otherwise it looks at the properties in the prototype (delegation).
We can have arbitrary objects as prototypes for another object.
Object has a method called
create() that instantiate an object given a prototype:
We can then verify whether an object is prototype of another. This considers indirect prototype inheritance as well, so, since
Object.prototype is prototype of
Object.prototype is prototype of
Object.prototype.toString function we get:
The difference is that while objects inherit from
Object.prototype, strings, arrays and functions inherit from
Function.prototype respectively. Since these prototypes are objects, strings, arrays and functions inherit from
Object.prototype as well:
Let’s take a closer look into functions. We can declare and call a function like this:
Let’s take a look at which properties are inherited from
One of them is
call, which we used above to invoke the function
Object.prototype.toString(). It takes several arguments. It will call the function and bind the first argument to
this within that function and the remaining of the arguments will be used as the actual arguments for the function. For example, if a function is defined as
We can invoke it by:
An alternative way to do that is using the function
apply, where you pass an explicit argument to be bound to
this, and the arguments in a array:
Having the parameter
this is important so we can have stateful function, which enables us to simulate object oriented patterns.
We can simulate a class with functions and prototypes. The function represents a constructor of the class, which will have the same name as the function, and methods are defined by adding functions to the prototype:
To make new instances, we can invoke the function with the operator
To understand how the
new operator works, we can implement a method that does the same:
We can simulate inheritance by instantiating an object and add properties to it:
Crockford  doesn’t like this pattern. His main argument is that if we forget the
new keyword when instantiating we can cause unexpected behavior, because if no object is bound to
this, it uses the global variable
His suggestion is not to use the class pattern at all, but rather work with prototypes inheritance directly.
We can already write ES6 syntax and use code transformers known as transpilers. Google has an open-source library called Traceur to transform ES6 syntax into ES5.
We can define a class representing a point:
It will generate this code: http://goo.gl/W7jFRU