The Web Security Topics Series

Objects

[...]

Superficially, JavaScript’s implementation of objects seems simple. An object is defined as a collection of named properties. In other words, it is a mapping from names to values, very much like a hash, lookup table or associative array in other programming languages. Since a function in JavaScript is a value, methods are just properties whose names map to functions. If obj is an object, and prop is the name of one of its properties, either of the expressions obj.prop or obj['prop'] can be used to obtain the property’s value. If this value is a function – so prop is a method – it can be called like any other function. In this case, the dot notation is usually preferred: obj.prop(a, b, c), for example. The square brackets are needed if the name is not a constant but has been computed dynamically. [...]

[...]

[Defining objects] is often done by using an object literal, which is just a way of listing a collection of properties. For example, suppose you have a sequence, perhaps a sequence of pages comprising a long article, and you need to be able to move forwards and backwards in the sequence. You could create an object to perform this job, as shown in Listing 10.

Listing 10

var counter = {
  _min: 1,
  _max: 10,
  _current: 1,

  next: function() { 
    if (++this._current > this._max )
        throw new Error('value is too large')
    return this
  },

  previous: function() { 
    if (--this._current < this._min )
        throw new Error('value is too small')
    return this
  },

  value: function() {
    return this._current
  }  
}

As you can see, the object literal is enclosed in curly brackets. Within these, there is a list of properties, each consisting of the property’s name (which must be a legal JavaScript name), followed by a colon and the property’s value. The properties in the list are separated by commas.

This object has six properties, of which three are data values. The other three are functions, so they are the object’s methods. Within each method’s body, a special variable called this refers to the object itself. Thus, the next and previous methods change the value of the _current property, and the value method returns its value. The values _min, _max and _current should never be accessed directly from outside the object. The use of an underscore at the beginning of their names is a convention that indicates this fact, but there is nothing to prevent a program referring to counter._current. In other words, JavaScript’s objects do not provide any data hiding. This is a significant deficiency which can only be rectified by using functions in a special way, as we will describe later.

[...]

You can assign objects to variables, as we did in Listing 10, pass them as arguments to functions, and return them as results. You may use an object literal in any of these contexts, and it is common to create an object as a literal while passing it to a function.

Objects are assigned and passed to functions by reference, which means that they are not copied. This means that an assignment creates an alias for an object, which is often a dangerous thing to do, but as we will see shortly, it is sometimes convenient. In the case of function calls, any changes made inside the called function will affect the original object.

[...]

The behaviour of the variable this, although consistent, can sometimes be surprising. We stated above that within each method’s body a special variable called this refers to the object itself, but although that seems straightforward it fails to take account of one of the worst features of JavaScript, the Global object. All the built-in constructors and several utility functions are properties of the Global object, and so are any functions that are defined without being methods of some other object. This includes functions defined at the top level of a program, as you might expect, but also functions defined locally inside methods, and all anonymous functions. References to the Global object are transparent: f() is interpreted as Global.f(), for example.

In the implementations of JavaScript in Web browsers, the window object is a property of the Global object, but the window object’s value is also the Global object, leading to the familiar phenomenon that unqualified names refer to properties of the window object. In Node.js, the variable global behaves in the same way.

The existence of the Global object means that it is possible to use this in the body of any function: if the function was not defined as a method of some other object, the value of this will be the Global object. Confusion may ensue.

A common mistake is to assume that this behaves like a free variable if it is used inside the body of an anonymous function called from a method. It doesn’t do that. Instead, it behaves as we have just described. You may find this clearer in Listing 12. The same thing happens if the anonymous function is assigned to a variable or defined as a named function inside g.

Listing 12

var obj = {
  f: function(fun) {
    // this is obj
    fun()
  },
  g: function() {
    // this is obj
    this.f(function() {
    // this is Global
    })
  }
}

Often, it is necessary to access the value of a method’s parent object inside an anonymous function used within the method. As Listing 12 shows, using this to refer to the parent object doesn’t work. There are two ways that do work, though.

The “high-tech” way makes use of a method called bind, which is a property of all functions. (We will explain how this comes about shortly.) If f is a function, taking n arguments a1, a2, ..., an, f.bind is a function taking n+1 arguments, a, a1, a2, ..., an. Within this new function, this is initialized to a and all the other arguments are passed as normal. In other words, calling bind through f with a as the first argument makes f behave as though it was a method of the object a. Hence, in the example shown in Listing 12, instead of passing an anonymous function to the method f, using this.f(function() { ... }), you would bind the function to obj and call this.f(function() { ... }.bind(this)).

The “low-tech” way is simply to save the value of this in a local variable, often called self, on entry to a method, and to refer to self instead of this inside any anonymous or local functions in the method, as in Listing 13.

Listing 13

var obj = {
  f: function(fun) {
    fun()
  },
  g: function() {
    var self = this
    // this is obj
    this.f(function() {
    // this is Global, but self is obj
    })
  }
}

(Some programmers prefer to call the local variable that, so they can write var that = this.) This low-tech solution is simple, immediately comprehensible, and less ugly than the high-tech solution, so it is often to be preferred.

[...]


End of Extract


[Extracted from Javascript on the Server Using Node.js and Express by Nigel Chapman and Jenny Chapman]

For an alternative description of Javascript objects and inheritance, see the blog post Understanding JavaScript OOP by Quildreen Motta.