What Is There Behind a Class in CoffeeScript?

CoffeeScript is a little language that compiles into JavaScript. CoffeeScript is gaining lots of popularity due to its simplicity and it is really popular in the Ruby community having lots of similarity with Ruby. CoffeeScript comes with the notion of ”class”. Class?? JavaScript doesn’t have class, right? True, but JavaScript has the concept of inheritance built-in the language. JavaScript doesn’t use classes for inheritance, but it uses the ”prototype” object as you may know. Prototypal inheritance can be implemented in JS as the ”Object.create” method (available in ES5) does or as in the protoInherit() in the following snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// parent object
var parentObj = {
  prop1 : "value1",
  method1 : function(){ return 1; }
};

// prototypal inheritance through the protoInherit function
function protoInherit(parentObj) {
  function Temp(){};
  Temp.prototype = parentObj;
  return new Temp();
}

// child object inherits from parent
var childObj = protoInherit(parentObj);

console.log(childObj.prop1); // returns "value1"
console.log(childObj.method1()); // return 1

Quite straightforward: the prototype linked to the new object points to the object that we want to inherit from. In this way the new object gets all the properties and methods from the parent  object name ”parentObj” in the previous snippet.

Now, let’s go back to CoffeeScript. If you visit http://coffeescript.org/ and you scroll down to the section ”Classes, Inheritance, and Super”, you can see in the right hand how the inheritance is implemented and how a CoffeeScript class is translated into JavaScript. The method that is in charge of expressing inheritance is ”__extends” and below is the implementation used:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) {
  for (var key in parent) {
      if (__hasProp.call(parent, key))
          child[key] = parent[key];
  }

  function ctor() {
      this.constructor = child;
  }
  ctor.prototype = parent.prototype;
  child.prototype = new ctor;
  child.__super__ = parent.prototype;
  return child;
};

Not exactly the same code as in the previous snippet. Look confusing? Let’s have a better look. The function implementing the inheritance takes the ”child” and the ”parent” function as arguments. First of all, all the properties from the “parent” are copied in the “child” function. Then, the prototype object of the “child” function points to a temporary constructor, which prototype points to the “parent“‘s prototype. The ”super” property is attached to the “child” function and it points to the parent’s prototype, in case you need to refer to the parent function. Finally the “child” function is returned.

Basically the classical inheritance pattern has been implemented here and it is an alternative to express inheritance in JavaScript. It makes sense in this context as CoffeeScript is trying here to emulate the behaviour of classes, familiar for Ruby, Java or C# developers, and to hide the prototype’s behaviour, which can be confusing for non-JavaScript developers.

I personally still like using the “prototype” object for inheritance, as it seems more a native thing from the language. Anyway, hope to have clarified the meaning of the code behind a “class” in CoffeeScript.

Comments