This article is a continuation of my JavaScript series. I highly recommend reviewing JavaScript - Part One and JavaScript - Part Two before proceeding.

Objects

As highlighted in JavaScript - Part One, almost everything in JavaScript is an object.

However, it is also possible to create your own objects. There are a few ways to create a new object:

  • Create a single object, using an object literal.
  • Create a single object, with the keyword new.
  • Define an object constructor (see below), and then create new objects.

The object literal is the easiest (most readable) way to create a new object. The structure of a “object literal” can be found below:

var objectName = {property1:"value", property2:"value"};


Note that the syntax is similar to an array, except for the use of { ... } and objects use “name:value” pairs.

All objects in JavaScript inherit from at least one other object. The object being inherited from is known as the prototype (see below), and the inherited properties can be found in the prototype object of the constructor.

Prototypes

Prototype-based programming is a style of object-oriented programming in which behaviour reuse (known as inheritance) is performed via a process of cloning existing objects that serve as prototypes. This model can also be known as prototypal, prototype-oriented, classless, or instance-based programming.

A prototype is like a blueprint for a JavaScript object.

All JavaScript objects inherit their properties and methods from their prototype. For example, objects created using an object literal (see above), inherit from a prototype called “Object.prototype”.

All other Javascript objects include their own prototypes and inherit from above (with the “Object.prototype” being the top of the prototype chain). The diagram below highlights this inheritance through prototypes.

alt text

It is important to note that although the properties and methods are inherited, they are still “owned” by prototypes, not the inheriting Object.

The main advantage of prototype-based programming is reuse, which helps simplify code and improve efficiency. For example, if you wanted to add some values or functionality to all* objects of a similar type (e.g. String), you could update the “String.prototype”.

An example of a simple “String.prototype” update can be found below:

var moto = "Keep things simple";  

String.prototype.countLetters = function (letter){  
  var letterCount = 0;  
  for (var i = 0; i < this.length; i++) {  
    if (this.charAt(i).toUpperCase() == letter.toUpperCase()) {  
    letterCount++;  
    }  
  }  
  return letterCount;  
};  

moto.countLetters("e");


In this example, I declare a new variable moto and then modify the String.prototype with a new method called countLetters. The method accepts a letter and returns the letter count. In the example the returned value would be “3”, as the letter “e” is referenced 3 times in the strong “Keep things simple”.

Constructors

A constructor allows you to set up inheritance while also assigning specific property values. This can be useful when looking to create many objects of one type.

An example of an “object constructor” being created can be found below:

function Hat(shoeSize, hatColor, hatStyle) {  
  this.size = hatSize;  
  this.color = hatColor;  
  this.construction = hatStyle;  
  this.putOn = function() {alert("The hat is on!");};  
}


In this example, a new object constructor is created called Hat, which includes some properties and a new method. It should also be noted that a popular convention in JavaScript is to capitalize the first letter of a constructor (making the code easier to read).

Once the object constructor has been created, you can create new objects of the same type. For example:

var baseballCap = new Hat("small", "black", "baseball");
baseballCap.putOn();


The baseballCap.putOn(); method will result in the user being alerted with the message “The hat is on!”.

Scope

In JavaScript, scope refers to the current context of your code. JavaScript has two scopes:

  • global
  • local

Any variable declared outside of a function belongs to the global scope, and is therefore accessible from anywhere in your code. Each function has its own scope, and any variable declared within that function is only accessible from that function and any nested functions (e.g. all functions have access to the scope “above” them).

A closure is a function having access to the parent scope, even after the parent function has closed.

Hoisting

Hoisting is the JavaScript interpreter’s default behaviour of moving variable and function declarations to the top of the current scope. However, variable initializations and function expressions are not hoisted.

An example of variable and function declarations can be found below. These will be hoisted.

var a;  
function(y, z) { return y * z };


An example of variable initializations and function expressions can be found below. These will not be hoisted.

var a = 7;  
var z = function(x, y) { return x * y };


Hoisting can be the root cause of many JavaScript bugs. To help avoid these issues, I advocate a single variable declaration at the beginning of every scope, as this is how the JavaScript interpreter reads the code.