A simple class-declaration for JavaScript+JQuery
This repository has been archived on 2026年05月25日 . You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
- JavaScript 81.3%
- HTML 10%
- Makefile 8.7%
=head1 NAME
jqsimple-class.js - a simple class-declaration for JavaScript
=head1 SYNOPSIS
jClass({
_constructor: function() { initialization stuff },
_destructor: function () { destruction stuff },
method1: function () { },
method2: function () {}
});
jClass.extend(existing, {
_constructor: function () { meh },
method1: function () { },
method2: function () { }
});
jClass.extendS(existing, {
_constructor: function () { meh },
method1: function () { },
method2: function () { }
});
=head1 DESCRIPTION
jQsimple-class is a simple class-declaration for JavaScript. It
allows you to easily declare classes, inherit from other classes and lets
you have constructors inline with your class declaration.
The basic syntax is simple:
var obj = jClass({
_constructor: function() { initialization stuff },
method1: function () { },
method2: function () {}
});
This makes a new class called 'obj', with the constructor defined, and the
methods defined. The constructor will be called when 'new obj' is called.
You can also extend existing classes, as long as those classes are also using
jQsimple-class. The syntax for this is:
var extendedObj = jClass.extend(obj, {
_constructor: function () { my init stuff },
method3 : function () { }
});
Now extendedObj is a class that inherits from obj. When 'new extendedObj'
is called the constructor defined for 'extendedObj' is executed first, then
the contructor for obj is executed.
If you want to inherit a class, but not call its constructor (or any
inherited constructors further up the chain), use extendS instead, the
result is the same with the exception of the constructor:
var extendedObj = jClass.extendS(obj, {
_constructor: function () { my init stuff },
method3 : function () { }
});
=head1 METHODS
=head2 To build classes
=over
=item B<jClass({})>
This is the basic class building function. It will build a class and return
its constructing function. Basic use is: I<var myClass = jClass({})>. Then you
can create instances of myClass by running I<var myInstance = new myClass()>.
The JavaScript hash/object you supply to this method is just like any other,
with the exception of the fact that if it has an entry named '_constructor', then
that will be used as the constructor for the class instance, and it will
recieve all the parameters that is supplied when running I<new myClass()>.
This means that if you have a constructor with the signature I<(debug)> and
a user runs I<new myClass(true)> then the constructor will recieve the value
I<true> for the parameter I<debug>. See I<jClass.extend> and I<jClass.extendS>
for information about inheritance and constructors.
=item B<jClass.extend(parent, {})>
This is a function that builds a class that inherits another class (which must
also have been declared using jQsimple-class). It will inherit all methods
of parent, override any methods that exist both in the parent and child and the
constructor for parent will be called when constructing the object. See the
section I<Constructors, destructors and inheritance> for more information on
constructors and destructors.
You can also inherit multiple classes, the syntax for that is:
B<jClass.extend([ parent1, parent2 ], {})>. See the section titled
I<Inheritance resolution order> for information about the resolution order.
See also I<jClass.extendS>.
=item B<jClass.extendS(parent, {})>
This works exactly like I<jClass.extend>, with the exception that this will not
call constructors or destructors further up the chain. Only a single
constructor and destructor will be executed, and that is the one defined in the
object that is inheriting (the child). If that does not have any constructor/destructor,
then no constructor/destructor will be executed.
As with I<jClass.extend()> You can also inherit multiple classes without inheriting
their constructors or destructors, the syntax for that is:
B<jClass.extendS([ parent1, parent2 ], {})>. See the section titled
I<Inheritance resolution order> for information about the resolution order.
=item B<jClass.virtual({})>
This works like I<jClass({})>, but creates a virtual class rather than a proper
class. The difference is that a virtual class can not be instantiated, but
it can be extended (and the resulting object can be instantiated as
per usual). This is useful for writing base classes that does nothing
useful unless they are extended as part of another class.
It is not possible to create virtual classes that extend other classes, they
can only act as base classes extended by others. A virtual class can include
a constructor and destructor just like normal classes.
=back
=head2 On classes and object instances
When you create a class using jQsimple-class, any resulting object AND class
will inherit a .jClass. namespace from jQsimple-class (and .jClass is therefore
reserved for internal use). The methods available depends on if you are running
them on the class itself, or an instance (an instance being the one you get
from "new myClass" while the class itself is the one returned from jClass() and
similar functions).
=head3 On both
=over
=item B<.jClass.version>
The version number of the jQsimple-class library in use.
=back
=head3 On object instances
The namespace .jClass. is reserved for future use.
=over
=item B<.destroy()>
Calls any destructors defined for the object, then completely destroys
the instance of the object it is called on (removing all attributes and methods,
only leaving behind an empty object equivalent to {}).
=back
=head1 CONSTRUCTORS AND DESTRUCTORS
The I<_constructor> is the method called when instantiating an object. It recieves
all parameters supplied.
The I<_destructor> is the method called when a user runs I<obj.destroy()> (but not
when the JS garbage collector removes it). It takes no parameters and should
handle any action you want to take when a user decides to explicitly destroy
an object.
Both the constructor and destructor are optional. If you don't need them, simply
omit them from the class definition. Both construction and I<obj.destroy()> will
work just fine without them.
=head2 Constructors, destructors and inheritance
When using I<jClass.extend> (not I<jClass.extendS>), all constructors and destructors
are inherited. The highest level constructor/destructor is called first, followed
by the next one in the chain and so on all the way down. All constructors recieve
all construction parameters supplied. Therefore it is a good idea to use key-value
hashes/objects as the sole parameter, rather than named positional parameters, so that
it is possible to supply useful values to all constructors, if that is needed.
=head1 INHERITANCE RESOLUTION ORDER
The inheritance resolution order used by jQsimple-class is rather simplistic,
but will work very well in all but the most complex cases. Consider the
traditional diamond inheritance pattern:
<A>
/ \
<B> <C>
\ /
<D>
Here B<A> inherits from B<B> and B<C>, and both B<B> and B<C> inherits B<D>.
Stupid resolution would end up with the chain A-B-D-C-D or A-B-D-C.
jQsimple-class will resolve this to A-B-C-D.
The inheritance definition expressed in JS code with jClass:
var D = jClass({});
var B = jClass.extend(D,{});
var C = jClass.extend(D,{});
var A = jClass.extend([B,C], {});
=head2 Algorithm
The algorithm for it is simple: once all of the classes to inherit has been
found, it will go through all of them, and each time it finds a class that has
been inherited twice it will push that to the back of the chain. Here's an
example of how it would resolve the above diamond pattern:
1. A - base
2. AB - inherited B
3. ABD - B inherited D
4. ABDC - A inherited C
5. ABCD - C also inherited D, but D was originally in front of C in the chain
and its entry was thus pushed back to behind C
=head1 COMMONJS MODULE
Using the jQsimple-class CommonJS module is simple. Put the commonjs build of
jQsimple-class somewhere in your module include path as jqsimple-class.js.
Then load jQsimple-class:
var jClass = require('jqsimple-class').jClass;
From there on you can use jClass as normal.
=head1 EXAMPLES
=over
=item B<Building a simple class>
var myClass = jClass({
_constructor: function ()
{
this.log('Yay');
},
log: function(msg)
{
console.log(msg);
}
});
var myInstance = new myClass(); // Logs 'Yay' to the console
myInstance.log('Hooray'); // Logs 'Hooray' to the console
=item B<Extending a simple class>
This overrides the log method of the above class to be a bit smarter
var myBetterClass = jClass.extend(myClass, {
enableLog: true,
_constructor: function(enableLog)
{
this.enableLog = enableLog;
},
log: function (msg)
{
if(this.enableLog && console && console.log)
{
console.log(msg);
}
}
});
var myInstance = new myClass(true); // Logs 'Yay' to the console, if it is present
var myInstance2 = new myClass(); // Does not log anything
=item B<Extending a simple class and removing the constructor>
This becomes myClass without any constructor, so it does not run log() on
load.
var mySilentClass = jClass.extendS(myClass, {});
var mySilentInstance = new mySilentClass(); // Does not log anything
=item B<Extending multiple classes>
var myUtils = jClass.virtual({
utilMeth: function () { }
});
var myUI = jClass.virtual({
showMessage: function () { }
});
var myClass = jClass.extend([myUtils,myUI],{
_constructor: function ()
{
this.showMessage(this.utilMeth('Hi'));
}});
=back
=head1 BUGS AND LIMITATIONS
jQsimple-class does not extend classes in a way that allows JavaScript to
recognize the inherited classes using 'instanceof' (an instance is a instanceof
the top-level class, but none of the lower level ones). This might be fixed in
the future.
=head1 AUTHOR
Eskild Hustvedt, E<lt>code@zerodogg.orgE<gt>
=head1 LICENSE AND COPYRIGHT
Copyright (C) 2010 by Eskild Hustvedt
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.