Creating classes
Classes are the basic building blocks of many object-oriented systems.
JavaScript 1.x (a.k.a. ECMAScript 3) does not support classes natively,
although it has prototype objects and constructor functions that look a lot
like classes in terms of syntax. Creating class-based programs in JavaScript
can be cumbersome, but jsclass
makes it easier.
// In the browser JS.require('JS.Class', function(Class) { ... }); // In CommonJS var Class = require('jsclass/src/core').Class;
To make a class, you just ask for a new Class()
, and list the names of
the methods the class has as regular JavaScript functions.
var Animal = new Class({ initialize: function(name) { this.name = name; }, speak: function(things) { return 'My name is ' + this.name + ' and I like ' + things; } });
Classes are expected to have an initialize()
method, though this is not
essential if no parameters are used to construct instances. The initialize()
method is called when you make an instance of the class, and is passed the
parameters used to instantiate the new object.
var nemo = new Animal('Nemo'); // nemo.name == "Nemo" nemo.speak('swimming') // -> "My name is Nemo and I like swimming"
Inheriting from a parent class
Let’s say we want to model a more specific kind of animal. We can create a
class Dog
as follows:
var Dog = new Class(Animal, { speak: function(stuff) { return this.callSuper().toUpperCase() + '!'; }, huntForBones: function(garden) { // ... } });
Dog
does not need its own initialize()
method as it inherits one from
Animal
. However, it chooses to override the speak()
method with its own
version.
Now we come to a special method generated by jsclass
, called callSuper()
.
This method gets created dynamically inside method calls and allows you to
access the current method in the parent class. Similar to Ruby, you don’t have
to pass any arguments to callSuper()
, thus avoiding repetition. The
arguments given to the current method are automatically passed by
callSuper()
up to the parent method.
var rex = new Dog('Rex'); rex.speak('barking') // -> "MY NAME IS REX AND I LIKE BARKING!"
callSuper()
only exists while there are super-calling methods on the stack,
and only if there is an actual super method to dispatch to. If there are no
inherited methods to call, the callSuper
is undefined.
rex.callSuper(); // -> rex.callSuper is not a function
You can pass arguments to callSuper()
to override the ones passed in
automatically, e.g.:
var Dog = new Class(Animal, { speak: function(stuff) { stuff = stuff.replace(/[aeiou]/ig, '_'); return this.callSuper(stuff).toUpperCase() + '!'; } }); var rex = new Dog('rex'); rex.speak('something') // -> "MY NAME IS REX AND I LIKE S_M_TH_NG!"
When overriding arguments you should note that callSuper()
always passes all
the current method’s arguments, minus the specifically overridden ones. So if
you have a method that takes arguments A
, B
, C
, D
, and E
and inside
that method you call
this.callSuper('one', 'two')
then the code that actually runs is
this.callSuper('one', 'two', C, D, E)
Ruby’s inheritance system is more powerful than simply calling methods in parent classes. For more information on how it works, refer to the inheritance article.