Tom said:
I know how to define new methods for Array objects, like:
Array.prototype.append = function(element)
// Add element to the end of the array
{
this[this.length] = element
}
append(x) will be a valid for any array. But (to structure
my code) I would like to introduce methods for a descendant
class of Array, so
that I can use specialArray.doSomething()
where doSomething() is defined only for arrays of class
specialArray.
I can't find a way of doing this but I'm sure one of you
experts can give me a hint.
Javascript has no 'classes' (or it only has one 'class') so when you speak
of classes is relation to javascript what you would usually be doing is
talking about emulating the concept of 'class' in javascript, and there are
many way to achieve that emulation.
Because there is only one type of object (the native ECMAScript object) in
javascript the way in which objects may be classified is by taking note of
the modifications that they undergo (usually when created); objects that
undergo 'like' modifications may be regarded as begin instances of the same
'class'.
Some of the modifications that an object undergoes in association with its
creation are automatic, such as the assignment of a value to the objects
internal [[Prototype]] property when it is created vial the - new - operator
applied to a function, and others are programmed (i.e. with the code inside
a constructor).
There are many ways creating object instances that have undergone
sufficiently 'like' modifications for them to be regarded as instances of a
'class'. The most obvious is the use of the - new - operator with a function
that is to be used as a constructor, along with modifications to the -
prototype - property of that constructor:-
function AnObject(x){
thisx = x;
}
AnObject.prototype.aMethod = function(){
return this.x;
}
var instance = new AnObject(3);
But a 'factory' function approach is just as viable (if at least a little
less efficient):-
function getAnObject(x){
var obj = new Object();
obj.x = x;
obj.aMethod = forAnObjectMethod;
}
function forAnObjectMethod(){
return this.x;
}
var instance = new getAnObject (3);
The above has (apart from a few minor details) the same outcome as the use
of the constructor above. However, the 'factory' approach can get round some
limitations of the 'constructor' method. This is particularly useful in with
regard to Array objects. What makes an Array special is that it is an
instance of the native ECMAScript object that has a special internal [[Put]]
method, but because that method is internal it cannot be modified by JS
code, and it is not inherited through the prototype chain. So doing
something like:-
function AnObject(x){
thisx = x;
}
AnObject.prototype = new Array();
var instance = new AnObject(3);
-does not result in an object that inherits the Array's special [[Put]]
method (even if it does inherit all the other methods of an array), because
the resulting object will have its own [[Put]] method and that will be the
normal object [[Put]] method. The 'factory' approach gets around this
problem because it creates a real Array and then modifies that Array
instance:-
function getAnObject(x){
var obj = new Array(); // or better var obj = [];
obj.x = x;
obj.aMethod = forAnObjectMethod;
}
function forAnObjectMethod(){
return this.x;
}
var instance = new getAnObject (3);
This object is a modified Array and so has the Array's special [[Put]]
method.
A similar process can be applied to function objects as will, giving the
possibility of having instances of a 'class' that are also callable (and you
will not see that in many other languages).
Another role for 'factory'-like functions is adding interfaces to other
objects. This can be analogous to 'subclassing' in some uses. So we might
have the previous augmented array object and 'subclass' it by passing (some
of) its instances through another function:-
function addSomeInterface(obj){
obj.anInterfaceMethod = forAnInterfaceMethod;
}
function forAnInterfaceMethod(){
return this.y;
}
var instance = addSomeInterface(new getAnObject (3));
Richard.