I'm trying to subclass Array
, following the ideas and recommendations given in this article.
One important goal of this subclass of Array
, which here I'm calling ArrayBase
, is that it be itself more straightforward to subclass than Array
itself. I'm finding that achieving this goal is surprisingly difficult. (But it may look this way to me because I'm a JavaScript n00b!)
Below is an implementation of ArrayBase
that is based on the ideas presented towards the end of the article cited earlier, with some enhancements of my own. I've also included an implementation of ArrayBase.slice
, since it illustrates one problem with the scheme1.
function ArrayBase () {
var arr = Array.prototype.constructor.apply(null, arguments);
var ctor = arr.constructor = arguments.callee;
arr.__proto__ = ctor.prototype;
return arr;
}
ArrayBase.prototype = new Array;
ArrayBase.prototype.slice = function () {
var ctor = this.constructor;
return ctor.apply(null,
Array.prototype.slice.apply(this, arguments));
}
var a0 = new ArrayBase(0, 1, 2, 3);
var a1 = a0.slice(2); // [2, 3]
console.log(a1 instanceof ArrayBase); // true
console.log(a1 instanceof Array); // true
So far, so good. The problem happens when I now try to subclass ArrayBase
. I find that the only way to do this requires basically replicating the entire ArrayBase
constructor (the only difference, very slight, happens in the first line). As inheritance goes, this is pitiful...
function MyArray () {
var arr = ArrayBase.apply(this, arguments);
var ctor = arr.constructor = arguments.callee;
arr.__proto__ = ctor.prototype;
return arr;
}
MyArray.prototype = new ArrayBase;
// behavior of MyArray
var a2 = new MyArray(1, 2, 3, 0);
var a3 = a2.slice(1); // [2, 3, 0]
console.log(a3 instanceof MyArray); // true
console.log(a3 instanceof ArrayBase); // true
console.log(a3 instanceof Array); // true
console.log(a3.join(':')); // "2:3:0"
a3[5] = 1;
console.log(a3.length); // 6
a3.length = 2;
console.log(a3.toString()) // "2,3"
My questions:
How could the duplication that exists between the
ArrayBase
andMyArray
constructors, be eliminated, while still preserving the behavior illustrated by the lines after the// behavior of MyArr
line? Would the scheme work also at the time of subclassingMyArray
?
(I'm aware of the arguments against building tall towers of inheritance, but whether they are good design or not, I want them to be at least soundly implemented.)
1If inheritance from Array
were as I think it should be, it would not be necessary to implement ArrayBase.slice
, but unfortunately the slice
method that ArrayBase
inherits from Array
does not show the elementary OOP courtesy of returning an object of the same class as that of this
.