HTML Data Port

© 2005 Goetz Heller

Table of Contents Classes Copyright Note back

Classes: Module Definition

How to Write a Class Module in JavaScript

Since prior to JavaScript Version 2 - which as of today is not in common use - the language has only limited support for classes and no support for namespaces at all, there is no syntax to handle these constructs, e.g. there is no class inheritance comparable to other commonly used object oriented languages. Taking this into consideration, we need to follow some guidelines in order to get comparable results. Luckily, this does not impose to much burden on our shoulders. The hardest inconvenience is calling super class methods where we need to supply the complete superclass ID in combination with the use of the call() function. This could be simplified somehow if namespace shortcuts were added to the class definition. For the sake of clearity I left this out from the following recommendations. Note that there is no reason why you should not store multiple modules in one file - on the contrary, in a load-on-demand situation, this could speed up things because fewer connections to the server are needed. Compare this to downloading Java jar files.

    12 Guidelines For Implementing Classes (order matters!)
  1. choose a name for the class including the containing namespace hierarchy, eg. full.Class.Name.String (which is a string)
  2. if you want to derive from a base class, retrieve it into a variable:
    var baseClass=core.getClassByID(full.Base.Class.Name.String);
  3. create the class constructor locally by assigning a function with an empty body to a variable, eg.
    var cls=function(){};
  4. add a class method classID() to the variable which returns the full class name
  5. optionally, override the class methods isAbstract() and isFinal() to make them return the value 'true'
  6. define any class specific constants as class properties
  7. if class cls is to be derived from base class baseClass, add the statement
    core.derive(cls, baseClass);
  8. optionally, add a method initialize() to the variable cls,
    cls.prototype.initialize=function(arg0, arg1, ...) { ...};
    If derived from baseClass, and if baseClass has a member initialize(), add the statement
    core.getClassByID(base.Class.Name.String).prototype.initialize.call(this, Arg0, Arg1, ...);
    to the method body.
    It is good practice to add this method even if it does nothing. Subclasses inherit this method automatically from the base class if it exists there. In such cases, if the subclass does not contribute its own functionality here, the inherited method does not need to be overridden. The purpose of it is to setup the data structures - i.e. instance variables - of an instance of the class.
  9. optionally, add a method reset() to the variable cls,
    cls.prototype.reset=function() { ...};
    If derived from class baseClass, and if base has a member reset(), add the statement
    core.getClassByID(base.Class.Name.String).prototype.reset.call(this);
    to the method body.
    It is good practice to add this member even if it does nothing. Subclasses inherit this method automatically from the base class if it exists there. In such cases, if the subclass does not contribute its own functionality here, the inherited method does not need to be overridden. The purpose of it is to erase and/or initialize all data from the instance variables of an instance of the class. Normally, it will be called from initialize(), too.
  10. add class specific methods to the class prototype.
  11. install the class with this final line
    core.installClass(cls);
  12. wrap the whole by the catch block of a corresponding try block where existence of class full.Class.Name.String is tested:
    try {
      eval(full.Class.Name.String);
    } catch(e) { // don't install twice
      // dependencies
      try {
        eval('core');
      } catch(e) {
        throw new Error('full.Class.Name.String: class \'core\' not installed');
      }
      // more dependency checks
      ...
      // module definitions go here
      ...
    } // end catch