I have been asked to review the book “Object-Oriented JavaScript” by Stoyan Stefanov, and published by Packt Publishing. The review is not quite ready yet, but in the meantime, here’s some exclusive content from the book for you to have a look at.

The following topics are discussed in this article:

Every function has a prototype property and it contains an object

Adding properties to the prototype object

Using the properties added to the prototype

The difference between own properties and properties of the prototype

__proto__ , the secret link every object keeps to its prototype

, the secret link every object keeps to its prototype Methods such as isPrototypeOf(), hasOwnProperty(), and

propertyIsEnumerable()

The prototype Property

The functions in JavaScript are objects and they contain methods and properties. Some

of the common methods are apply() and call() and some of the common

properties are length and constructor. Another property of the function

objects is prototype.

If you define a simple function foo() you can access its properties as you

would do with any other object:

>>>function foo(a, b){return a * b;} >>>foo.length

2

>>>foo.constructor

Function()

prototype is a property that gets created as soon as you define the function.

Its initial value is an empty object.

>>>typeof foo.prototype



“object”

It’s as if you added this property yourself like this:

>>>foo.prototype = {}

You can augment this empty object with properties and methods. They won’t have any

effect of the foo() function itself; they’ll only be used when you use

foo()as a constructor.

Adding Methods and Properties Using the Prototype

Constructor functions can be used to create (construct) new objects. The main idea is

that inside a function invoked with new you have access to the value this,

which contains the object to be returned by the constructor. Augmenting (adding methods

and properties to) this object is the way to add functionality to the object being

created.

Let’s take a look at the constructor function Gadget() which uses this

to add two properties and one method to the objects it creates.

function Gadget(name, color) { this.name = name; this.color = color; this.whatAreYou = function(){ return 'I am a ' + this.color + ' ' + this.name; } }

Adding methods and properties to the prototype property of the constructor

function is another way to add functionality to the objects this constructor produces.

Let’s add two more properties, price and rating, and a getInfo()

method. Since prototype contains an object, you can just keep adding to it like

this:

Gadget.prototype.price = 100; Gadget.prototype.rating = 3; Gadget.prototype.getInfo = function() { return 'Rating: ' + this.rating + ', price: ' + this.price; };

Instead of adding to the prototype object, another way to achieve the above

result is to overwrite the prototype completely, replacing it with an object of your

choice:

Gadget.prototype = { price: 100, rating: 3, getInfo: function() { return 'Rating: ' + this.rating + ', price: ' + this.price; } };

Using the Prototype’s Methods and Properties

All the methods and properties you have added to the prototype are directly available

as soon as you create a new object using the constructor. If you create a newtoy object

using the Gadget() constructor, you can access all the methods and properties

already defined.

>>> var newtoy = new Gadget('webcam', 'black'); >>> newtoy.name;

“webcam”

>>> newtoy.color;

“black”

>>> newtoy.whatAreYou();

“I am a black webcam”

>>> newtoy.price;

100

>>> newtoy.rating;

3

>>> newtoy.getInfo();

“Rating: 3, price: 100”

It’s important to note that the prototype is “live”. Objects are passed by reference

in JavaScript, and therefore the prototype is not copied with every new object instance.

What does this mean in practice? It means that you can modify the prototype at any time

and all objects (even those created before the modification) will inherit the

changes.

Let’s continue the example, adding a new method to the prototype:

Gadget.prototype.get = function(what) { return this[what]; };

Even though newtoy was created before the get() method was defined,

newtoy will still have access to the new method:

>>> newtoy.get('price');

100

>>> newtoy.get('color');

“black”

Own Properties versus prototype Properties

In the example above getInfo() used this internally to address the object. It

could’ve also used Gadget.prototype to achieve the same result:

Gadget.prototype.getInfo = function() { return 'Rating: ' + Gadget.prototype.rating + ', price: ' + Gadget.prototype.price; };

What’s is the difference? To answer this question, let’s examine how the prototype

works in more detail.

Let’s again take our newtoy object:

>>> var newtoy = new Gadget('webcam', 'black');

When you try to access a property of newtoy, say newtoy.name the

JavaScript engine will look through all of the properties of the object searching for one

called name and, if it finds it, will return its value.

>>> newtoy.name

“webcam”

What if you try to access the rating property? The JavaScript engine will

examine all of the properties of newtoy and will not find the one called rating. Then the

script engine will identify the prototype of the constructor function used to create this

object (same as if you do newtoy.constructor.prototype). If the property is found

in the prototype, this property is used.

>>> newtoy.rating

3

This would be the same as if you accessed the prototype directly. Every object has a

constructor property, which is a reference to the function that created the object, so in

our case:

>>> newtoy.constructor

Gadget(name, color)

>>> newtoy.constructor.prototype.rating

3

Now let’s take this lookup one step further. Every object has a constructor. The

prototype is an object, so it must have a constructor too. Which in turn has a prototype.

In other words you can do:

>>> newtoy.constructor.prototype.constructor

Gadget(name, color)

>>> newtoy.constructor.prototype.constructor.prototype

Object price=100 rating=3

This might go on for a while, depending on how long the prototype chain is, but you

eventually end up with the built-in Object() object, which is the highest-level

parent. In practice, this means that if you try newtoy.toString() and newtoy

doesn’t have an own toString() method and its prototype doesn’t either, in the end

you’ll get the Object’s toString()

>>> newtoy.toString()

“[object Object]”

Overwriting Prototype’s Property withOwn Property

As the above discussion demonstrates, if one of your objects doesn’t have a certain

property of its own, it can use one (if exists) somewhere up the prototype chain. What if

the object does have its own property and the prototype also has one with the same name?

The own property takes precedence over the prototype’s.

Let’s have a scenario where a property name exists both as an own property and as a

property of the prototype object:

function Gadget(name) { this.name = name; } Gadget.prototype.name = 'foo';

“foo”

Creating a new object and accessing its name property gives you the object’s

ownname property.

>>> var toy = new Gadget('camera'); >>> toy.name;

“camera”

If you delete this property, the prototype’s property with the same name”shines

through”:

>>> delete toy.name;

true

>>> toy.name;

“foo”

Of course, you can always re-create the object’s own property:

>>> toy.name = 'camera'; >>> toy.name;

“camera”

Object-Oriented JavaScript

Create scalable, reusable high-quality JavaScript applications and libraries Learn to think in JavaScript, the language of the web browser

Object-oriented programming made accessible and understandable to web developers

Do it yourself: experiment with examples that can be used in your own scripts

Write better, more maintainable JavaScript code For more information, please visit:

http://www.PacktPub.com/object-oriented-javascript-applications-libraries/book

Enumerating Properties

If you want to list all properties of an object, you can use a for-in loop. In

Chapter 2, you saw how you could loop through all the elements of an array:

var a = [1, 2, 3]; for (var i in a) { console.log(a[i]); }

Arrays are objects, so you can expect that the for-in loop works for objects

too:

var o = {p1: 1, p2: 2}; for (var i in o) { console.log(i + '=' + o[i]); }

This produces:

p1=1

p2=2

There are some details to be aware of:

Not all properties show up in a for-in loop. For example, the length (for

arrays) and constructor properties will not show up. The properties that do show up are

called enumerable . You can check which ones are enumerable with the help of the

propertyIsEnumerable() method that everyobject provides.

loop. For example, the length (for arrays) and constructor properties will not show up. The properties that do show up are called . You can check which ones are enumerable with the help of the method that everyobject provides. Prototypes that come through the prototype chain will also show up, provided they are

enumerable. You can check if a property is an own property versus prototype’s using the

hasOwnProperty() method.

enumerable. You can check if a property is an own property versus prototype’s using the method. propertyIsEnumerable() will return false for all of the prototype’s

properties, even those that are enumerable and will show up in thefor-in

loop.

Let’s see these methods in action. Take this simplified version of

Gadget():

function Gadget(name, color) { this.name = name; this.color = color; this.someMethod = function(){return 1;} } Gadget.prototype.price = 100; Gadget.prototype.rating = 3;

Creating a new object:

var newtoy = new Gadget('webcam', 'black');

Now if you loop using a for-in, you see of the object’s all properties,

including those that come from the prototype:

for (var prop in newtoy) { console.log(prop + ' = ' + newtoy[prop]); }

The result also contains the object’s methods (as methods are just properties that

happen to be functions):

name = webcam

color = black

someMethod = function () { return 1; }

price = 100

rating = 3

If you want to distinguish between the object’s own properties versus the prototype’s

properties, use hasOwnProperty(). Try first:

>>> newtoy.hasOwnProperty('name')

true

>>> newtoy.hasOwnProperty('price')

false

Let’s loop again, but showing only own properties:

for (var prop in newtoy) { if (newtoy.hasOwnProperty(prop)) { console.log(prop + '=' + newtoy[prop]); } }

The result:

name=webcam

color=black

someMethod=function () { return 1; }

Now let’s try propertyIsEnumerable(). This method returns true for own

properties that are not built-in:

>>> newtoy.propertyIsEnumerable('name')

true

Most built-in properties and methods are not enumerable:

>>> newtoy.propertyIsEnumerable('constructor')

false

Any properties coming down the prototype chain are not enumerable:

>>> newtoy.propertyIsEnumerable('price')

false

Note, however, that such properties are enumerable if you reach the object contained

in the prototype and invoke its propertyIsEnumerable().

>>> newtoy.constructor.prototype.propertyIsEnumerable('price')

true

isPrototypeOf()

Every object also gets the isPrototypeOf() method. This method tells you

whether that specific object is used as a prototype of another object.

Let’s take a simple object monkey.

var monkey = { hair: true, feeds: 'bananas', breathes: 'air' };

Now let’s create a Human() constructor function and set its prototype property

to point to monkey.

function Human(name) { this.name = name; } Human.prototype = monkey;

Now if you create a new Human object called george and ask: “Is

monkey george’s prototype?”, you’ll get true.

>>> var george = new Human('George'); >>> monkey.isPrototypeOf(george)

true

The Secret __proto__ Link

As you know already, the prototype property will be consulted when you try to access a

property that does not exist in the current object.

Let’s again have an object called monkey and use it as a prototype when

creating objects with the Human() constructor.

var monkey = { feeds: 'bananas', breathes: 'air' }; function Human() {} Human.prototype = monkey;

Now let’s create a developer object and give it some properties:

var developer = new Human(); developer.feeds = 'pizza'; developer.hacks = 'JavaScript';

Now let’s consult some of the properties. hacks is a property of thedeveloper

object.

>>> developer.hacks

“JavaScript”

feeds could also be found in the object.

>>> developer.feeds

“pizza”

breathes doesn’t exist as a property of the developer object, so the

prototype is looked up, as if there is a secret link pointing to the prototype

object.

>>> developer.breathes

“air”

Can you get from the developer object to the prototype object? Well, you could, using

constructor as the middleman, so having something like

developer.constructor.prototype should point to monkey. The problem is that

this is not very reliable, because constructor is more for informational purposes and can

easily be overwritten at any time. You can overwrite it with something that’s not even an

object and this will not affect the normal functioning of the prototype chain.

Let’s set the constructor property to some string:

>>> developer.constructor = 'junk'

“junk”

It seems like the prototype is now all messed up:

>>> typeof developer.constructor.prototype

“undefined”

…but it isn’t, because the developer still breathes “air”:

>>> developer.breathes

“air”

This shows that the secret link to the prototype still exists. The secret link is

exposed in Firefox as the __proto__ property (the word “proto” with two

underscores before and two after).

>>> developer.__proto__

Object feeds=bananas breathes=air

You can use this secret property for learning purposes but it’s not a good idea to use

it in your real scripts, because it does not exist in Internet Explorer, so your scripts

won’t be portable. For example, let’s say you have created a number of objects with

monkey as a prototype and now you want to change something in all objects. You can

change monkey and all instances will inherit the change:

>>> monkey.test = 1

1

>>> developer.test

1

__proto__ is not the same as prototype. __proto__ is a property of the

instances, whereas prototype is a property of the constructor functions.

>>> typeof developer.__proto__

“object”

>>> typeof developer.prototype

“undefined”

Once again, you should use __proto__ only for learning or debugging

purposes.

Object-Oriented JavaScript