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
Arraywithout using theclass extendssyntax, which is surprising to someone who has only seen theclasssyntax described as syntactical sugar for prototypal inheritance, since it means that theclass extendssyntax can't be fully desugared to the non-classsyntax. It means that describing theclasssyntax 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-classsyntax is a second-class citizen in the language. Adding a method for using the native subclassing without theclass extendssyntax would be consistent with ES5 addingObject.create()that allows using prototypal inheritance without thenewoperator.The new method could be called
Object.inherits(); a simplified example of how it could be used:It's currently impossible to inherit the behavior of exotic builtin objects like `Array` without using the `class extends` syntax, which is surprising to someone who has only seen the `class` syntax described as syntactical sugar for prototypal inheritance, since it means that the `class extends` syntax can't be fully desugared to the non-`class` syntax. It means that describing the `class` 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 the `class extends` syntax would be consistent with ES5 adding `Object.create()` that allows using prototypal inheritance without the `new` operator. The new method could be called `Object.inherits()`; a simplified example of how it could be used: ```class Foo extends Array() {} // ...desugars to function Foo() { function Foo(...args) { return Object.getPrototypeOf(Foo)(...args) } Object.inherits(Foo, Array) return Foo } Object.inherits = function(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype, { constructor: {value: subClass}, [Symbol.species]: {value: subClass}, }) Object.setPrototypeOf(subClass, superClass) // make subClass imbue the objects it constructs with native exotic behavior here }``` -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160504/dd3efda9/attachment.html>