HTML5 Zone is brought to you in partnership with:

Diego Fernandez is an interaction designer and UI developer working at Mulesoft. He loves design in its many forms: from object oriented design to graphic design. Before joining Mulesoft, Diego worked on UI design and systems development for different industries like travel and financial. He also loves programming languages and had experience with Java, Smalltalk, Scala, Groovy, and more. Diego is a DZone MVB and is not an employee of DZone and has posted 2 posts at DZone. You can read more from them at their website. View Full User Profile

A Brief Introduction to JavaScript Objects

10.10.2013
| 3124 views |
  • submit to reddit

When you come from a class-based programming language, using objects in feels weird: Where is the class keyword? How can I do inheritance?

As we are going to see, JavaScript is actually pretty simple. It supports class-like definition of objects and single-inheritance out of the box.

But first, a small tip to change your reading experience: By using your browser JavaScript console, you can play with the examples without leaving this page:

  • Chrome: MacOSX Cmd-Alt-J / Windows Ctrl-Shift-J
  • Firefox: MacOSX Cmd-Alt-K / Windows Ctrl-Alt-K
  • Safari: Cmd-Alt-C (only if you enable the Develop menu on Advanced Settings)
  • IE8+: Press F12 and go to the console

The Basics

OK, all set. Now the first step, define an object:

var point = {x: 1, y: 2};
As you can see, the syntax is pretty straight-forward, and object members are accessed by the usual means:

point.x // gives 1
Also we can add properties at any time:

var point = {}; 
point.x = 1; 
point.y = 2;

The Elusive this Keyword

Now let's move on to more interesting things. We have a function that calculates the distance of a point to the origin (0,0):

function distanceFromOrigin(x, y) {     
  return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 
} 
The same function written as a method of point looks like this:
var point = {     
  x:1, y:2,     
  distanceFromOrigin: function () {         
    return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));     
  } 
}; 
If we evaluate: point.distanceFromOrigin(), the this keyword becomes point.
When you come from Java it may sound obvious, but as we go deep into the details of JavaScript, is not.

Functions in JavaScript are treated like any other value; it means that distanceFromOrigin doesn’t have anything special compared to the x and y fields. For example, we can re-write the code like this:

var fn = function () {     
  return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); 
}; 
var point = {x:1, y:2, distanceFromOrigin: fn };
How this is Determined?

JavaScript knows how to assign this, because of how distanceFromOrigin is evaluated:

point.distanceFromOrigin();
But doing just fn() will not work as expected: it will return NaN, cause this.x and this.y are undefined. Confused? Lets go back to our initial point definition:

var point = {
 x:1, y:2,
 distanceFromOrigin: function () {
 return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
 }
};
Since distanceFromOrigin is like any other value, we can get it and assign it to a variable:

var fn = point.distanceFromOrigin;
Again fn() returns NaN. As you can see from the two previous examples, when a function is defined there is no special binding with the object. The binding is done when the function is called: if the obj.method() syntax is used this is automatically set to the receiver. It’s Possible to Explicitly Set this?

JavaScript functions are objects, and like any object, they have methods.
In particular, a function has two methods apply and call, that executes the function but allows you to set the value for this:

point.distanceFromOrigin() // is equivalent to…
point.distanceFromOrigin.call(point);
For example:

function twoTimes() {
 return this * 2;
}
twoTimes.call(2); // returns 4

Defining Common Behavior

Now, suppose that we have more points:

var point1 = {
 x:1, y:2,
 distanceFromOrigin: function () {
 return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
 }
};
var point2 = {
 x:3, y:4,
 distanceFromOrigin: function () {
 return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
 }
};
It makes no sense to copy and paste this snippet each time that you want to have a point, so a small refactoring helps:

function createPoint(x, y) {
 var fn = function () {
 return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
 }
 return {x: x, y:y, distanceFromOrigin:fn};
}
var point1 = createPoint(1, 2);
var point2 = createPoint(3, 4);
We can create lots of points in this way, but:
  • It makes an inefficient use of memory: fn is created for each point.
  • Since there is no relationship between each point object, the VM cannot make any dynamic optimization. (OK, this is not obvious and depends on the VM, but it can impact on execution speed).

To fix these problems, JavaScript has the ability to do a smart copy of an existing object:

var point1 = {
 x:1, y:2,
 distanceFromOrigin: function () { 
 return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); 
 }
};
var point2 = Object.create(point1);
point2.x = 2;
point2.y = 3;
Object.create(point1) uses point1 as a prototype to create a new object. If you inspect point2 it will look like this:

x: 2
y: 3
__proto__
 distanceFromOrigin: function () { /* … */ }
 x: 1
 y: 2

NOTE:__proto__ is a non-standard internal field, displayed by the debugger. The correct way to get the object prototype is with Object.getPrototypeOf, for example: Object.getPrototypeOf(point2) === point1

This way of handling objects as copies of other objects is called prototype-based programming, and conceptually is simpler than class-based programming.

Published at DZone with permission of Diego Fernandez, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)