Ways to extend Array object in javascript
ES6
class SubArray extends Array {
last() {
return this[this.length - 1];
}
}
var sub = new SubArray(1, 2, 3);
sub // [1, 2, 3]
sub instanceof SubArray; // true
sub instanceof Array; // true
Using __proto__
(old answer, not recommended, may cause performance issues)
function SubArray() {
var arr = [ ];
arr.push.apply(arr, arguments);
arr.__proto__ = SubArray.prototype;
return arr;
}
SubArray.prototype = new Array;
Now you can add your methods to SubArray
SubArray.prototype.last = function() {
return this[this.length - 1];
};
Initialize like normal Arrays
var sub = new SubArray(1, 2, 3);
Behaves like normal Arrays
sub instanceof SubArray; // true
sub instanceof Array; // true
A while ago I read the book Javascript Ninja written by John Resig, the creator of jQuery.
He proposed a way to mimic array-like methods with a plain JS object. Basically, only length
is required.
var obj = {
length: 0, //only length is required to mimic an Array
add: function(elem){
Array.prototype.push.call(this, elem);
},
filter: function(callback) {
return Array.prototype.filter.call(this, callback); //or provide your own implemetation
}
};
obj.add('a');
obj.add('b');
console.log(obj.length); //2
console.log(obj[0], obj[1]); //'a', 'b'
I don't mean it's good or bad. It's an original way of doing Array
operations. The benefit is that you do not extend the Array prototype
.
Keep in mind that obj
is a plain object
, it's not an Array
. Therefore obj instanceof Array
will return false
. Think obj
as a façade.
If that code is of interest to you, read the excerpt Listing 4.10 Simulating array-like methods.
Method names should be lowercase. Prototype should not be modified in the constructor.
function Array3() { };
Array3.prototype = new Array;
Array3.prototype.add = Array3.prototype.push
in CoffeeScript
class Array3 extends Array
add: (item)->
@push(item)
If you don't like that syntax, and you HAVE to extend it from within the constructor, Your only option is:
// define this once somewhere
// you can also change this to accept multiple arguments
function extend(x, y){
for(var key in y) {
if (y.hasOwnProperty(key)) {
x[key] = y[key];
}
}
return x;
}
function Array3() {
extend(this, Array.prototype);
extend(this, {
Add: function(item) {
return this.push(item)
}
});
};
You could also do this
ArrayExtenstions = {
Add: function() {
}
}
extend(ArrayExtenstions, Array.prototype);
function Array3() { }
Array3.prototype = ArrayExtenstions;
In olden days, 'prototype.js' used to have a Class.create method. You could wrap all this is a method like that
var Array3 = Class.create(Array, {
construct: function() {
},
Add: function() {
}
});
For more info on this and how to implement, look in the prototype.js source code