Created
November 7, 2010 17:10
-
-
Save Gozala/666251 to your computer and use it in GitHub Desktop.
Array subclass ES5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// No need to sub class Array if what you need is just an extended | |
// array. Example below illustrates the way to extend Array. | |
function SubArray() { | |
return Object.defineProperties(Array.prototype.slice.call(arguments), SubArrayDescriptor) | |
} | |
SubArray.prototype = Array.prototype | |
var SubArrayDescriptor = | |
{ constructor: { value: SubArray } | |
, last: { value: function last() { | |
return this[this.length - 1] | |
}} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Sub classing array works as expected. Many people have false expectation that | |
// special behavior of number properties (sub[10]) is supposed to be inherited by a subclass. | |
function SubArray() { | |
var subArray = Object.create(SubArray.prototype) | |
Array.prototype.push.apply(subArray, arguments) | |
return subArray | |
} | |
SubArray.prototype = Object.create(Array.prototype, | |
{ constructor: { value: SubArray } | |
, last: { value: function last() { | |
return this[this.length - 1] | |
}} | |
}) |
I'd like to note that the above examples re-write Array.from
, which can break newer engines. For example, after the above patch, the following breaks in ES6:
Array.from( new Set([1,2,3,1,2,3]) )
The answers that use the patched Array.from
are for ES5, and the newer example should be used for ES6.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See the following examples showing various ways to do it (
Array.isArray
works).It is impossible to extend Array with pure ES5 as spec'd, but it was possible in some ES5 engines that had
__proto__
which was non-standard at the time (see [compatibility table for__proto__
}(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto#Browser_compatibility)).The problem is that
Array
always returns an object, and even if you call it with.call
or.apply
the returned value will not be what you specified in.call
or.apply
. For example,So, because of this, we need to modify the prototype of the value returned from
Array.apply
so that it inherits from our subclass prototype. This is where__proto__
comes in.Object.setPrototypeOf
was not around until ES6.So, here's various ways to do it. All the examples extend
Array
with ES5-stylefunction() {}
-based classes. The first few use ES6+ language features, and the last two use pure ES5 (except that__proto__
was only supported by some ES5 engines):