Tag Archives: constructors

Inheritance in JavaScript

In the last post, we saw how to implement class-like objects in JavaScript, despite the language’s lack of actual class data types. The solution used closure to create private fields, which can be either data or functions. Once you’ve got classes up and running, it’s natural to ask if it’s possible to simulate some of the other OOP concepts in JavaScript. Probably the most important of these is inheritance.

After poking about a lot and failing to find a convincing implementation of inheritance, I chanced upon a rather concise post by Steffen Rusitschka. He offers two ways of implementing inheritance, but although his code is fairly easy to use, he really doesn’t explain how it works, and that’s far from obvious. I’ll try to provide a bit of an explanation here.

I’ll look only at the closure-based version, since it follows on nicely from my last post.

At the heart of the technique is this helper code:

(function(){
  CClass = function(){};
  CClass.create = function(myConstructor) {
    var k = this;
    c = function() {
      this._super = k;
      var pubs = myConstructor.apply(this, arguments), self = this;
      for (key in pubs) (function(fn, sfn) {
        self[key] = typeof fn != "function" || typeof sfn != "function" ? fn :
          function() { this._super = sfn; return fn.apply(this, arguments); };
      })(pubs[key], self[key]);
    };
    c.prototype = new this;
    c.prototype.constructor = c;
    c.extend = this.extend || this.create;
    return c;
  };
})();

To use this code, we must first create the data types and then create objects from them. As a test, we will use these data types:

var X = CClass.create(function () {
  return {
    x: 3,

    test: function () { return 2 * this.x; }
  };
});

var Y = X.extend(function () {
  return {
    y: 4,

    test: function () { return this._super() + this.x + this.y; }
  };
});

var xx = new X;
var yy = new Y;

The X class (we’ll call them classes even though JavaScript doesn’t have classes as such; it’s easier to write about that way) has a single data field and a simple function which returns twice the data field. The Y class inherits X, adds a second data field, and overrides the test() function. Note that Y’s test() calls a function called _super(), which calls the base class version of test(). (It’s called ‘_super’ rather than ‘super’, since ‘super’ is a reserved word in JavaScript, even though it doesn’t do anything (yet).)

Once we’ve created the two classes, we can create objects from them in the usual way, using the ‘new’ operator. Let’s try to trace through this code to see what it’s doing.

First, note that the helper code at the top is actually run (notice the parentheses on line 18 at the bottom, which cause the preceding function to be run). Thus we create CClass as an empty function on line 2, and then define the create() function in the remaining code.

Now we look at the declaration of the X class. This is done by calling CClass.create() with the given function as the argument, so this function becomes myConstructor in the helper code. Since CClass is calling create(), ‘this’ refers to CClass, which is an empty function. This is saved in the variable k.

Now a function named c is defined. We’ll look at what it does in a minute, but note that at the end, its prototype is defined as ‘new this’, so the prototype gets a copy of CClass; also the constructor is set to the function c itself. On line 15, an extend() function is defined as either ‘this.extend’ if it’s defined or, if not, ‘this.create’. On the first call to create(), extend() won’t be pre-defined, so on this pass, extend is set to create and becomes the same function as create().

Also, note that the variables k and myConstructor as used inside the c function so, by closure, the values they had when the function was created are saved and are available to the c function when it is used later on.

The result of defining the X class is then to assign to X the c function produced by CClass.create(). Before we move on to Y, let’s see what happens when we create a new object using X, as we do on line 35.

This code treats X like a constructor, so the c function we just created gets called, and its ‘this’ is the object being created. Looking back at the first code block, we see that on line 6, this new object has its _super() defined as k, which you recall was set as the CClass earlier, and which is still available because of closure. Thus here, _super() becomes the empty function CClass.

On line 7, myConstructor() is called using JavaScript’s built-in apply() method, which specifies the calling object as the first argument (which is ‘this’ here) and then passes any arguments as an array (this will be empty in our simple example here). Remember that myConstructor contains the function defined on lines 19 to 25, so the result of this is that pubs contains a new object defined using that function.

Also on line 7, a ‘self’ variable is declared, and set to ‘this’. Since we haven’t actually created any data fields in our new object yet, ‘self’ at present is empty. The idea is to copy the fields from pubs to self so that the object created by constructor call (which is not pubs, since that was created by calling a different function) has the same fields as pubs.

The for loop on line 7 does this. It loops over each key in the pubs object. The body of the loop is another of those self-calling functions. Looking at line 11, we see that the arguments passed to the function are pubs[key] and self[key]. Since self is empty, all these elements will be undefined at this point. This means that the condition on line 9 ‘typeof sfn != “function”‘ will be true for every key, with the result that self[key] gets ‘fn’ assigned to it for every key. Since fn is the first function argument, this effectively runs self[key] = pubs[key], and copies pubs into self as required.

Thus the c function is a sort of roundabout way of implementing a constructor. However, the fun starts when we implement inheritance. On line 27, we create a Y class that inherits X by calling X.extend(). As before, the argument to extend() is a function which acts as a constructor for Y. When we created X, remember that extend() got assigned to create(), so calling X.extend() really calls X.create(). The process is similar to before, except that ‘this’ on line 4 now refers to X rather than CClass. The c function assigned to Y contains the same code as that assigned to X, but the values of k and myConstructor are those in force when X.extend() was called, using closure.

The main differences happen on lines 13 to 15. The prototype is defined as ‘new this’, which means it gets a copy of X. Remember that the prototype of a constructor is what’s the __proto__ of an object created from that constructor points to, so new objects created from this constructor will have all the fields of X.

On line 15, this.extend does exist now so it gets assigned to c.extend.

Now let’s see what happens if we create a Y object, as on line 36. The ‘new’ operator creates a new object by first pointing this object’s __proto__ at the constructor’s prototype. Remember we set Y’s prototype to an X object, so this means that the new Y object yy will inherit the fields of X right at the start. That is, ‘this’ will effectively b an X object at the start of the construction process, so ‘self’ gets assigned to an X object on line 7.

How about pubs, also on line 7? It is initialized by calling myConstructor, which contains the function on lines 27 to 33. This code knows nothing about X, so pubs contains only those fields specified in the Y constructor. Here, we have 2 fields: y and an override of test().

The for loop on line 8 runs for these 2 fields (but not for x, since that’s not mentioned in the Y constructor). For the y field, self[‘y’] is undefined, so it gets assigned to pubs[‘y’] and gets the value 4. However, when we look at the ‘test’ key, self[‘test’] does exist since there was a test() defined in X. In this case both conditions on line 9 are false (both fn and sfn are functions) so self[key] gets assigned to the function on line 10. Because of closure, the values of sfn and fn are saved when this is done.

The result of this is that, when Y’s version of test() is called, this._super gets set to the saved value of sfn, which is X’s version of test(), and then fn (which is Y’s version of test()) gets called via the apply() method. That is, whenever a method in the derived class is called, the corresponding base class method (if any) is available through this._super(). This means, of course, that the function referred to by this._super() varies, depending on which function calls it.

In my experience over years of ‘normal’ OOP using Java and C#, I have used a super() method only a handful of times, so you probably won’t need to use it that much. However, this clever solution makes it available in JavaScript if you need it.

Advertisements

JavaScript objects

After many years as an OO programmer using primarily C++, Java and C#, I’m finally taking a first look at JavaScript. At the lower syntax level, that of most operators, expressions, if statements and loops, JavaScript is much like other OO languages such as C# and Java. Above that level, things diverge quite rapidly. I’ll have a look at how JavaScript handles objects (in the OO sense) here.

One of the big differences between JavaScript and other mainstream OO languages (I’ll use C# as the main point of comparison from here on, as it’s the language I’m using for most other stuff) is that JavaScript is an untyped language. That is, you don’t need to (in fact, you can’t) specify the data type of a variable when it is declared. JavaScript has the ‘var’ keyword which should be used when declaring a variable. (I say ‘should be used’ since it is possible to declare a variable without using ‘var’, but this effectively makes the variable global, which is usually undesirable, so it’s best not to do it.)

However, JavaScript’s var is not the same as C#’s var. In C#, once a variable has been declared using var (or indeed, declared using any method), the data type of that variable is fixed. In the case of C#’s var, the data type is determined by the object to which that variable is initialized. In JavaScript, the data type of a variable is mutable, so you can, for example, declare a variable and assign a string to it, and later assign a different type such as a number. JavaScript is therefore loosely typed.

Another difference is that although objects are used in JavaScript, classes are not. This might seem contradictory; how can you have an object if it’s not an instance of a class? In this sense, JavaScript objects are similar to anonymous types in C#. An object can be created by simply listing some name-value pairs. For example, if we wanted an object that represents a book, we could write:

var bookObj = {
  author: "Delaney",
  title: "Nova",
  price: 5.47
}

This form of object is called an object literal, since it is a literal description of what one particular object contains. We could then use this object in a browser page by writing (assuming that the above code is stored in the file /Scripts/ObjectTest.js relative to the home page):

<h2>Books</h2>
<script src="~/Scripts/ObjectTest.js"></script>
<script>
    document.writeln(bookObj.author + ': <i>' + bookObj.title + '</i>  £' + bookObj.price + "<br>");
</script>

(We could, of course, have put the document.writeln() statement in the file as well, but this way we can see how to use the results of the first script in a script within the browser.)

This method is fine if we’re content to create single objects, but one of the powers of traditional OO languages is the ability to define a new data type (the class) and then create a number of objects of that data type. How do we do that in JavaScript?

It turns out that although JavaScript doesn’t have a class as such, it has a structure that, in practice, is very close to one, at least in the way it can be used. A class can be simulated in JavaScript by using a function.

A JavaScript function is actually an object in the same way that the untyped object above is. That is, a function can be created and passed around the program like any other object. In this sense, JavaScript functions are similar to C# delegates.

All objects in JavaScript have a prototype object behind them. This has a number of implications which we’ll get to in due course, but for now we can think of it as a form of inheritance. Just as all C# classes by default inherit the ‘object’ class, all object literals like the example above are backed by the Object.prototype object.

All functions are backed by Function.prototype, but each individual function also has its own prototype object behind it. This prototype can be used to add methods to a function.

Functions have a wide variety of uses, which we’ll get to in due course, but for now, the one we are interested in is the constructor function. This looks a lot like a class definition in C#. Here’s a constructor for a Book object:

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

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

var book1 = new Book("Asimov", "Foundation", 3.55);
var book2 = new Book("Adams", "Hitchhiker's Guide to the Galaxy", 4.95);

The first 5 lines declare the constructor function, and define three data fields within it. All functions begin with the keyword ‘function’, followed by an argument list (which can be empty). As JavaScript doesn’t impose data types on its variables, this argument list contains no types, just parameter names.

The body of the constructor makes use of the keyword ‘this’. As in C#, ‘this’ refers to the object which called the function, so here, ‘this’ refers to the Book object that is being created. This code should look very similar to a constructor in C#.

Line 7 shows how to add a method to a Book object. We access the hidden prototype of the Book constructor, and then append the method name, which is ‘description’ here. The prototype is allowed to refer to ‘this’ in the same way as the original constructor. Here we just return a string containing some HTML to render the Book’s data in a browser.

The last two lines show how we can use the Book constructor to create a couple of objects. Again, these declarations look very similar to those in C#.

To use this code in a browser, we could put the following in the HTML file for the web page:

<h2>Books</h2>
<script src="~/Scripts/ObjectTest.js"></script>
<script>
    document.writeln(book1.description() + "<br>");
    document.writeln(book2.description() + "<br>");
</script>

Running the script from the file creates the book1 and book2 objects, and we can just call the description() method on them to obtain the HTML to render on the web page.

There are other ways of achieving the same result, but this little example should illustrate how JavaScript handles objects and object creation.