Tag Archives: Javascript objects

Functions and methods in JavaScript

JavaScript allows the creation of global functions, as in the simple example

function multiply(x, y) {
  return x * y;
}

This function can be called from anywhere using syntax such as var product = multiply(4, 5) which assigns the value 20 to product.

However, all functions are also objects and, as such, a function can be attached to another object as a data field. Functions that are fields of other objects are usually called methods.

Suppose we define  an object like this:

var number = { value: 0 }

This creates a single object called number which has a single data field called value. We can attach a method to number either as part of its definition, as in this attempt to define a method that squares number’s value:

var number = {
  value: 0,
  square: function() {
    return value * value;
  }
}

number.value = 42;
number.square();

If we run this code (try it in Chrome’s console), you probably won’t get the result you’re expecting. The call to number.square() returns NaN (not a number) rather than the expected value of 42 * 42 = 1764. What went wrong? Analogous code in a language like C# or Java would work, since we’re (kind of) treating number like a class with a data field and a method, and as we know, a class’s methods all have access to the class’s data fields.

JavaScript, as you’ve probably guessed, doesn’t work quite that way. If we refer to an unadorned variable like value, it is assumed that this is a global variable, so the square() method above looks for a global value and, not finding it, returns the indeterminate result of NaN.

You can test this by defining a global value variable and giving it a distinctive value, as in var value = 12; If you now run the line number.square() you’ll get the result 144, so it’s clear where the square() method is getting its ‘value’ from.

To solve this problem, we need to realize that any method gets a ‘bonus’ parameter passed to it, which is the object that calls the function. This object is referred to inside the function by the keyword this, which you’re probably familiar with from C# or Java. However, although using this as a prefix in C# is optional, in JavaScript it’s compulsory if you want to refer to the object calling the method. Thus our revised definition of number looks like this:

var number = {
  value: 0,
  square: function() {
    return this.value * this.value;
  }
}

number.value = 42;
number.square();

Now if we run the last 2 lines again, we get the expected result of 1764.

In fact, global functions are also passed a this parameter, except this time it refers to the global object, and use of this here actually is optional. For example, we could define the global function

function doubleValue() {
  return 2 * this.value;
}
doubleValue();

Running this code gives the result 24, since this.value now refers to the global value. We could equally well have defined this function as

function doubleValue() {
  return 2 * value;
}
doubleValue();

We’d get the same result.

This behaviour makes sense for truly global functions, but we run into problems if we declare functions inside methods. A rather contrived example is a revised version of the square function above. Suppose we define a new method for number called newSquare:

number.newSquare = function () {
  var innerSquare = function () {
    return multiply(this.value, this.value);
  }
  return innerSquare();
}

number.newSquare();

If number.value is still 42 and the global value is 12, running this code produces the value 144. Now what’s wrong? Even though we’ve included the this prefix when referring to value, the global value is still being used instead of number.value.

The problem here is what is widely regarded as a mistake in the design of JavaScript. Whenever a function that is not a field of an object (that is, a method) is called, this is always bound to the global object. The function innerSquare is a utility function declared within a method, but is not a method itself, so its this is the global object, not the number object that calls newSquare.

This sort of code design is very common, so there is a standard workaround to avoid this problem. Inner functions such as innerSquare do have access to local variables inside their container method, so we can define a local variable (usually called that) and assign it to point to this. We can then use that whenever we want to access the object that called the method. We therefore rewrite newSquare as follows:

number.newSquare = function () {
  var that = this;
  var innerSquare = function () {
     return multiply(that.value, that.value);
  }
  return innerSquare();
}

number.newSquare();

This time we get the correct result of 1764.

Advertisements

Prototypes in JavaScript

JavaScript’s prototype system is often confusing for programmers coming to the language from an object-oriented background, as with C# or Java. Here I’ll try to dispel a bit of confusion by looking at how object prototypes work.

For what follows, it’s very useful if you enter the code into a console (such as can be found in the Google Chrome browser) and experiment with the various commands.

We can create an object by writing its fields literally, as in

var comic = {
  title: 'Spider-man',
  issue: 343
}

Type this into the console and then examine the comic object (by just typing ‘comic’ (without the quotes) on a line by itself and hitting return). Its type is given as Object, which isn’t surprising. Open up this node, and you’ll see that in addition to the two fields ‘issue’ and ‘title’, there is a third field called (in Chrome, though this won’t be true in all browsers) __proto__, whose type is given as Object. If you expand __proto__, you’ll see a list of fields that include the functions that are defined for all objects, such as toString, hasOwnProperty and so on.

The __proto__ object is the prototype that is attached to all objects by default. In its expansion, you may notice that it does not have its own __proto__ field. This is because the prototype of Object is the end of the prototype chain (more on this later). Thus it is more correct to say that all objects except Object’s prototype have their own prototype.

So what use is this prototype? Its importance arises from the fact that you can customize it by adding fields to it, or replacing it completely with an object of your own making.

We saw in the post on creating objects with a constructor that we can add methods to objects by adding a method to the constructor’s prototype. Let’s have a closer look at what’s going on here.

First, we need to make one thing clear. It is true that all objects (including functions) have the prototype we’ve been referring to by the name __proto__. However, functions (and only functions) also have a separate ‘prototype’ property, where in this case, the word ‘prototype’ is spelled out in full and not abbreviated or enclosed in underscores. Please understand that __proto__ and ‘prototype’ are not the same; only __proto__ is the true prototype of an object or a function. So what’s the ‘prototype’ property of a function used for?

When we use the ‘new’ operator to create a new object from a constructor, the new operator creates the new object and then links the object’s __proto__ to the constructor’s ‘prototype’. Note that this is a reference link from the object to the constructor, and not a copy of the constructor’s prototype to the object’s __proto__. This means that any changes to the constructor’s prototype are reflected in the __proto__ of all objects created from it. More on this below.

For example, suppose we define the Book constructor as in the previous post (we’ve made a slight change in that the name of the constructor has been moved to the function definition rather than being a separate var, but the effect is the same):

function Book(author, title, price) {
  this.author = author;
  this.title = title;
  this.price = price;
};

var book1 = new Book("Asimov", "Foundation", 3.55);

Now examine ‘book1’ in the console. You’ll find that it contains the three data fields defined in the constructor and also __proto__. Expand __proto__, and you’ll see that it contains the constructor, along with another __proto__, the latter of which is the base Object prototype. If you expand the constructor, you’ll see that it contains its own __proto__ and also a ‘prototype’ of type Book. It’s this ‘prototype’ that is used to create new objects.

If we add a method to the constructor’s ‘prototype’ like this:

Book.prototype.description = function () {
  return this.author + ': <i>' + this.title + '</i>  £' + this.price;
}

we can examine the __proto__ of ‘book1’ again. Now we’ll find that the ‘description’ function has been added:

> book1
  Book
    author: "Asimov"
    price: 3.55
    title: "Foundation"
    __proto__: Object
      constructor: function (author, title, price) {
      description: function () {
      __proto__: Object

If we expand ‘description’, we find that it, too, has a __proto__ and a ‘prototype’, since it’s a function. However, its ‘prototype’ isn’t used for anything, since ‘description’ isn’t a constructor.

A neat trick is to use prototypes to create a new object that inherits its prototype from an existing object. To do this, we can add a new method to Object (so that it’s available to all our code). This is the ‘beget’ method, and is due to Douglas Crockford:

if (typeof Object.beget !== 'function') {
  Object.beget = function (copy) {
    var F = function () { };
    F.prototype = copy;
    return new F();
  };
}

var book3 = Object.beget(book1);

The initial ‘if’ checks if ‘beget’ has already been defined (if it hasn’t, the typeof will return ‘undefined’). We then define Object.beget as a function which takes a single argument copy. Inside beget(), we create an empty function called F, and assign this function’s ‘prototype’ (not __proto__) to be the object copy that we want to copy. F is treated as a constructor, and the ‘new’ operator is used to create a new object from F, which is then returned. Recall that using ‘new’ creates a new object whose __proto__ is a copy of the constructor’s ‘prototype’, so the effect is to generate a new object whose __proto__ is copy.

The book3 object inherits all the fields of book1 and is shown as being of type F. Expanding F, we find that its only field is __proto__, which is of type Book, and if we expand that, we get the same fields as we had for book1.

If we now access book3.title, we’ll get ‘Spider-man’ which of course was copied from book1. What’s important to note, though, is that the ‘title’ field isn’t in the top layer of fields for book3; it’s one layer down, in the Book prototype. This illustrates that JavaScript will look for a field iteratively from the top down, so if it doesn’t find the field you want at the top layer, it will look at the next layer, and then the next, and so on, until it either finds the field or hits the Object.__proto__ at the bottom. If it doesn’t find it there, it will return ‘undefined’.

The prototype chain includes only the __proto__ fields; the ‘prototype’ properties have nothing to do with this process. They are used only in the creation of new objects in a constructor.

What happens if we try altering the data fields in these objects? For example, suppose we try writing book3.author = ‘Simak’. We find that the ‘author’ field of book3 is indeed now Simak, but has this assignment affected anything on the prototype chain? We can examine book3’s structure once again to find out.

We find that, rather than altering the ‘author’ field in the Book __proto__, book3 has a new author field at the top level. That is, we now have

> book3
 F
  author: "Simak"
  __proto__: Book
    author: "Asimov"
    price: 3.55
    title: "Foundation"
    __proto__: Book

Assigning a new value to an existing field in a __proto__ doesn’t overwrite the existing value; it adds a new value at the layer above the __proto__.  JavaScript ‘knows’ which author to use, since when we request the author field, it starts at the top in its search, so the first author found will be Simak. If we remove that field with the statement delete book3.author, we find that the top layer author is removed, and the author property reverts to that stored in the __proto__, so it becomes ‘Asimov’ again.

What happens if we do change a property in the __proto__? Suppose we start with book1 and book3 as above (without the episode where we introduced ‘Simak’), so both books have ‘Asimov’ as their author. We now try writing book3.__proto__.author = “Delaney”. Now we find that the authors of both book1 and book3 have changed to Delaney, since we changed the underlying __proto__ on which both these books are defined. (By the way, fiddling with __proto__ directly isn’t terribly good programming practice, not least because not all browsers support it. We did it here just to illustrate a point.)

We can modify a constructor’s ‘prototype’ after the constructor has been used to create objects and these modifications will be available to the existing objects. This is because the __proto__ in an object is a pointer back to the constructor’s prototype that was used to create it. For example, we could add a method to Book by writing Book.prototype.getPrice = function() { return this.price; }. Having done that, we can now write book1.getPrice() to retrieve book1’s price of 3.55.

[Beware of a gotcha here, though. Since __proto__ is a reference to the constructor’s ‘prototype’, if you redefine the constructor’s prototype to point to a totally new object, the __proto__ reference won’t follow this change; it will still point to the old object. That is, it’s OK to modify fields and methods of the ‘prototype’ object originally associated with the constructor, but it’s not OK to replace that ‘prototype’ object.]