Adding a non-class-syntax method for subclassing native objects
I believe you can do this with Reflect.construct
.
function SubArray(arg1) {
return Reflect.construct(Array, arguments, new.target);
}
SubArray.prototype = Object.create(Array.prototype);
Reflect.setPrototypeOf(SubArray, Array);
var arr = new SubArray();
arr instanceof SubArray; // true
arr instanceof Array; // true
arr[5] = 0; // should exotically update length property
arr.length === 6; // true
edit: fixed an issue mentioned below
On May 3, 2016, at 8:01 PM, Michael Theriot <michael.lee.theriot at gmail.com> wrote:
I believe you can do this with
Reflect.construct
.
function SubArray(arg1) { return Reflect.construct(Array, arguments, SubArray);
this should probably be: return Reflect.construct(Array, arguments, new.target);
If you don’t pass new.target subclasses of SubArray (whether defined using a class declaration or procedurally) won’t be correctly constructed
Thanks, I had missed the Reflect.construct()
method. One problem with
your solution is that the Array
iterator methods like .map()
use
this.constructor[Symbol.species]
to construct their result, so the
prototype actually needs to be set like this:
SubArray.prototype = Object.create(Array.prototype, {
constructor: {
value: SubArray,
writeable: true,
enumerable: false,
configurable: false,
}
})
Setting the constructor
property on the prototype is part of the
MakeConstructor operation (for full parity the prototype
property should
be defined as non-enumerable, non-configurable as well).
It would be helpful to have the MakeConstructor operation implemented as
Reflect.makeConstructor(F, writablePrototype, prototype)
, since otherwise
the alternative to the class extends
syntax is very verbose. It would
also be consistent with the Reflect.construct()
method corresponding to
the Construct abstract operation, and Object.create()
mainly
corresponding to ObjectCreate.
It's currently impossible to inherit the behavior of exotic builtin objects like
Array
without using theclass extends
syntax, which is surprising to someone who has only seen theclass
syntax described as syntactical sugar for prototypal inheritance, since it means that theclass extends
syntax can't be fully desugared to the non-class
syntax. It means that describing theclass
syntax as syntactical sugar should be qualified to be fully accurate (since trying to desugar it with, for example, Babel can potentially break things even in browsers that otherwise support native subclassing), and that non-class
syntax is a second-class citizen in the language. Adding a method for using the native subclassing without theclass extends
syntax would be consistent with ES5 addingObject.create()
that allows using prototypal inheritance without thenew
operator.The new method could be called
Object.inherits()
; a simplified example of how it could be used: