Subclassing JavaScript's Array class
I kept reading over and over again that you just can't subclass Array in JavaScript. Well where I come from (America that is), can't is a four letter word. Fortunately for us, everybody was just plain wrong, and to prove it, I'll demonstrate in JavaScript and Coffeescript.
var Wrapper = function() {
var name = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
this.push.apply(this, args);
return this;
}
Wrapper.prototype = Object.create(Array.prototype);
With a design like this you can pass an arbitrary number of arguments into your wrapper, do what you want with the first n, and use the rest in your collection. Methods like .pop()
and properties like length
will work out of the box.
Of course Coffeescript gives us the opportunity to pretend that prototypal inheritance doesn't exist, if you're into that sort of thing:
class ArrayWrapper extends Array
constructor: (title, args...) ->
@title = title
@push.apply(@, args)
Enjoy!
Written by Sam Slotsky
Related protips
3 Responses
hi...
first, why do you skip the first argument and assign it to an unused variable name
???
second, the resulting pseudo-array does not behave like an array, try this:
var Wrapper = function() {
var args = Array.prototype.slice.call(arguments, 0);
this.push.apply(this, args);
return this;
}
Wrapper.prototype = Object.create(Array.prototype);
Wrapper.prototype.first = function(){ return this[0] };
var a = new Wrapper('cool',1,2,3);
a.length = 6; //OK
;a.map(function(x) {return x*2}); //OK
a.push('last one'); //OK
;a.first(); //OK
a.length = 3;
a[6]; //it is still there!!!! WRONG, should be undefined
so you see, you still haven't subclassed a Javascript Array ;-)
Hello, your post helped me, but I want to suggest improvement:
class ArrayWrapper extends Array
method: -> console.log 'hello'
new ArrayWrapper().method() # This doesn't work!
It is can't be called "class" without methods, so:
class ArrayWrapper
proto = ArrayWrapper.prototype = Object.create Array.prototype
proto.method = -> console.log 'hello' # Yes, we are loosing simple methods notations
new ArrayWrapper().method() # great!
Markdown in this site infuriates me
Note this class ArrayWrapper extends Array
is fully supported in the most recent versions of Chrome, Edge, and Firefox. Although, something akin to what you have provided is definitely needed for older browsers. A middle ground would be to use Proxies, which seem to pre-date Array inheritance support in Edge and Firefox. See https://medium.com/@anywhichway/array-sub-classing-with-support-461ff7c3b819.