Next: , Previous: , Up: Interoperability   [Contents]


4.2 Prototypally Extending Classes

Since classes are also constructors with prototypes, they may be used as part of a prototype chain. There are, however, some important considerations when using any sort of constructor as part of a prototype chain.

Conventionally, prototypes are subtyped by using a new instance as the prototype of the subtype’s constructor, as so:

  var Foo = Class( { /*...*/ } );

  // extending class as a prototype
  function SubFoo() {};
  SubFoo.prototype = Foo();  // INCORRECT
  SubFoo.prototype.constructor = SubFoo;

Figure 4.2: Incorrectly prototypally extending GNU ease.js classes

The problem with this approach is that constructors may perform validations on their arguments to ensure that the instance is in a consistent state. GNU ease.js solves this problem by introducing an asPrototype method on all classes:

  var Foo = Class( { /*...*/ } );

  // extending class as a prototype
  function SubFoo()
  {
      // it is important to call the constructor ourselves; this is a
      // generic method that should work for all subtypes, even if SubFoo
      // implements its own __construct method
      this.constructor.prototype.__construct.apply( this, arguments );

      // OR, if SubFoo does not define its own __construct method, you can
      // alternatively do this:
      this.__construct();
  };
  SubFoo.prototype = Foo.asPrototype();  // Correct
  SubFoo.prototype.constructor = SubFoo;

Figure 4.3: Correctly prototypally extending GNU ease.js classes

The asPrototype method instantiates the class, but does not execute the constructor. This allows it to be used as the prototype without any issues, but it is important that the constructor of the subtype invokes the constructor of the class, as in Figure 4.3. Otherwise, the state of the subtype is undefined.

Keep in mind the following when using classes as part of the prototype chain:


Next: , Previous: , Up: Interoperability   [Contents]