Reputation: 42390
I want to subclass a javascript Array and pass constructor arguments to the array. What I have is:
function SubArray(arguments) {
Array.apply(this, arguments);
}
SubArray.prototype = Array.prototype;
Test does not indicate that arguments are being passed to the Array
var x = new SubArray("One", "Two", "Three");
// Object[]
// x.length = 0
Whereas when I do this with an Array I get this
var x = new Array("One", "Two", "Three");
// Object["One", "Two", "Three"]
// x.length = 3
What am I doing wrong?
Upvotes: 4
Views: 796
Reputation: 66404
In ES6 you can extend Array using the class
syntax
class SubArray extends Array {
constructor() {
super(...arguments);
}
first() {
return this[0];
}
}
length will work as expected
var sa = new SubArray('foo', 'bar');
sa[2] = 'baz';
sa.length; // 3
sa.first(); // "foo"
sa instanceof SubArray; // true
Up to and including ES5 there is no way to cleanly extend Array
in the usual constructor-prototype way without losing functionality, instead you have to add properties to an Array instance
function SubArray() {
var arr = Array.apply(null, arguments);
arr.first = function () {return this[0];};
return arr;
}
Using this no longer requires new
as an Object is returned from the function, and instanceof
will not be able to determine SubArray.
var sa = SubArray('foo', 'bar');
sa[2] = 'baz';
sa.length; // 3
sa.first(); // "foo"
sa instanceof SubArray; // false -- this gets broken
In an ES5 environment where behaviour is more important than speed, you can force the prototype chain as desired using Object.setPrototypeOf
(see MDN warning), this is "a bit of a hack" and would look like
function SubArray() {
var arr = Array.apply(null, arguments);
Object.setPrototypeOf(arr, SubArray.prototype);
return arr;
}
SubArray.prototype = Object.create(Array.prototype);
SubArray.prototype.first = function () {return this[0];};
Again, new
is no-longer required but this time the behaviour of instances is exactly as would be expected if it was extended normally.
var sa = SubArray('foo', 'bar');
sa[2] = 'baz';
sa.length; // 3
sa.first(); // "foo"
sa instanceof SubArray; // true
Upvotes: 6