Skip to content

Instantly share code, notes, and snippets.

@trusktr
Last active September 3, 2018 18:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trusktr/c74867851a335dcc20aca6c614feabe7 to your computer and use it in GitHub Desktop.
Save trusktr/c74867851a335dcc20aca6c614feabe7 to your computer and use it in GitHub Desktop.
Extending Array with ES5-style class constructors
// With some ES2015+ language features:**
{
function MyArray(...args) {
const self = new Array(...args)
self.__proto__ = MyArray.__proto__
return self
}
MyArray.prototype = {
__proto__: Array.prototype,
constructor: MyArray,
add(...args) {
this.push(...args)
},
}
MyArray.__proto__ = Array
const a = new MyArray
assert( a instanceof Array )
assert( a instanceof MyArray )
a.add(1,2,3)
assert( a.length === 3 )
assert( a.concat(4,5,6).length === 6 )
assert( a.concat(4,5,6) instanceof MyArray )
assert( Array.isArray(a) )
}
//**With Reflect.construct, and ES2015+ language features:**
{
function MyArray(...args) {
const self = Reflect.construct(Array, args, new.target)
return self
}
// with ES6+ features:
MyArray.prototype = {
__proto__: Array.prototype,
constructor: MyArray,
add(...args) {
this.push(...args)
},
}
MyArray.__proto__ = Array
const a = new MyArray
assert( a instanceof Array )
assert( a instanceof MyArray )
a.add(1,2,3)
assert( a.length === 3 )
assert( a.concat(4,5,6).length === 6 )
assert( a.concat(4,5,6) instanceof MyArray )
assert( Array.isArray(a) )
}
//**ES5 version with `new`, but uses non-standard __proto__ which may not be available in all ES5 engines:**
~function() {
function MyArray() {
// we need the null for the following bind call
var args = [null].concat( Array.prototype.slice.call(arguments) )
var self = new ( Array.bind.apply(Array, args) )
self.__proto__ = MyArray.prototype
return self
}
function assign(target, source) {
// naive implementation, can be improved
for (var key in source) {
target[key] = source[key]
}
return target
}
MyArray.prototype = assign( Object.create(Array.prototype), {
constructor: MyArray,
add: function() {
this.push.apply(this, Array.prototype.slice.call(arguments))
},
concat: function() {
var args = Array.prototype.slice.call(arguments)
return MyArray.from( Array.prototype.concat.apply( this, args ) )
},
})
MyArray.__proto__ = Array // static inheritance
MyArray.from = function( other ) {
var result = new this
other.forEach( function( item, index ) {
result[index] = item
})
return result
}
var a = new MyArray
assert( a instanceof Array )
assert( a instanceof MyArray )
a.add(1,2,3)
assert( a.length === 3 )
assert( a.concat(4,5,6).length === 6 )
assert( a.concat(4,5,6) instanceof MyArray )
assert( Array.isArray(a) )
}()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment