Darien Valentine (2018-07-24T02:24:01.000Z)
valentinium at gmail.com (2018-07-24T02:40:30.560Z)
> That, and that the existing builtins already impose those limitations - and only class allows you to do those things, with them. I’m surprised by that statement — it appeared to me that it currently remains possible to create classes, including classes that extend built-ins, without class syntax. ``` const test = value => { if (typeof value !== 'string') throw new TypeError('nope'); return value; }; function StringSet(init) { if (new.target === undefined) throw new TypeError('StringSet is not a constructor'); if (init !== undefined) init = Array.from(init, test); return Reflect.construct(Set, [ init ], new.target); } Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: Object.setPrototypeOf({ add(value) { return super.add(test(value)); } }, Set.prototype).add }); Reflect.defineProperty(StringSet.prototype, Symbol.toStringTag, { configurable: true, value: 'StringSet' }); Reflect.setPrototypeOf(StringSet, Set); Reflect.setPrototypeOf(StringSet.prototype, Set.prototype); new StringSet('abc'); ``` Not that this is something one is apt to want to do normally, though it being possible does remain useful sometimes for meta/compositiony stuff. It cannot be achieved in an <= ES5 environment, but it seems all the reflection tools needed are present in environments that actually have class syntax — even, despite the awkwardness necessitated by HomeObject stuff, what is needed to employ super in methods. I’m curious if, aside from the possibility of implementation-specific things like type error messages being different, there there is anything about the above class which ends up observably different from the ES-side from one created with class syntax instead? --- Edit: I can think of one. Because of how the home object’s prototype has been set for `add` here, reassigning the prototype of `StringSet.prototype` will not affect the super reference resolution as it would in a class-syntax class. This can be very awkwardly addressed too, though: ``` Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: { add(value) { return Reflect.getPrototypeOf(Reflect.getPrototypeOf(this)).add.call(this, test(value)); } }.add }); ``` (To clarify I’m not obv not suggesting this is better than `class StringSet extends Set { ... }`, just want to understand what can’t presently be done other ways.)
valentinium at gmail.com (2018-07-24T02:39:43.615Z)
> That, and that the existing builtins already impose those limitations - and only class allows you to do those things, with them. I’m surprised by that statement — it appeared to me that it currently remains possible to create classes, including classes that extend built-ins, with class syntax. ``` const test = value => { if (typeof value !== 'string') throw new TypeError('nope'); return value; }; function StringSet(init) { if (new.target === undefined) throw new TypeError('StringSet is not a constructor'); if (init !== undefined) init = Array.from(init, test); return Reflect.construct(Set, [ init ], new.target); } Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: Object.setPrototypeOf({ add(value) { return super.add(test(value)); } }, Set.prototype).add }); Reflect.defineProperty(StringSet.prototype, Symbol.toStringTag, { configurable: true, value: 'StringSet' }); Reflect.setPrototypeOf(StringSet, Set); Reflect.setPrototypeOf(StringSet.prototype, Set.prototype); new StringSet('abc'); ``` Not that this is something one is apt to want to do normally, though it being possible does remain useful sometimes for meta/compositiony stuff. It cannot be achieved in an <= ES5 environment, but it seems all the reflection tools needed are present in environments that actually have class syntax — even, despite the awkwardness necessitated by HomeObject stuff, what is needed to employ super in methods. I’m curious if, aside from the possibility of implementation-specific things like type error messages being different, there there is anything about the above class which ends up observably different from the ES-side from one created with class syntax instead? --- Edit: I can think of one. Because of how the home object’s prototype has been set for `add` here, reassigning the prototype of `StringSet.prototype` will not affect the super reference resolution as it would in a class-syntax class. This can be very awkwardly addressed too, though: ``` Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: { add(value) { return Reflect.getPrototypeOf(Reflect.getPrototypeOf(this)).add.call(this, test(value)); } }.add }); ``` (To clarify I’m not obv not suggesting this is better than `class StringSet extends Set { ... }`, just want to understand what can’t presently be done other ways.)
valentinium at gmail.com (2018-07-24T02:37:01.816Z)
> That, and that the existing builtins already impose those limitations - and only class allows you to do those things, with them. I’m surprised by that statement — it appeared to me that it currently remains possible to create classes, including classes that extend built-ins, with class syntax. ``` const test = value => { if (typeof value !== 'string') throw new TypeError('nope'); return value; }; function StringSet(init) { if (new.target === undefined) throw new TypeError('StringSet is not a constructor'); if (init !== undefined) init = Array.from(init, test); return Reflect.construct(Set, [ init ], new.target); } Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: Object.setPrototypeOf({ add(value) { return super.add(test(value)); } }, Set.prototype).add }); Reflect.defineProperty(StringSet.prototype, Symbol.toStringTag, { configurable: true, value: 'StringSet' }); Reflect.setPrototypeOf(StringSet, Set); Reflect.setPrototypeOf(StringSet.prototype, Set.prototype); new StringSet('abc'); ``` Not that this is something one is apt to want to do normally, though it being possible does remain useful sometimes for meta/compositiony stuff. It cannot be achieved in an <= ES5 environment, but it seems all the reflection tools needed are present in environments that actually have class syntax — even, despite the awkwardness necessitated by HomeObject stuff, what is needed to employ super in methods. I’m curious if, aside from the possibility of implementation-specific things like type error messages being different, there there is anything about the above class which ends up observably different from the ES-side from one created with class syntax instead? --- Edit: I can think of one. Because of how the home object’s prototype has been set for `add` here, reassigning the prototype of `StringSet.prototype` will not affect the super reference resolution as it would in a class-syntax class. This can be very awkwardly addressed too, though: ``` Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: { add(value) { return Reflect.getPrototypeOf(Reflect.getPrototypeOf(this)).add.call(this, test(value)); } }.add }); ```
valentinium at gmail.com (2018-07-24T02:33:48.207Z)
> That, and that the existing builtins already impose those limitations - and only class allows you to do those things, with them. I’m surprised by that statement — it appeared to me that it currently remains possible to create classes, including classes that extend built-ins, with class syntax. ``` const test = value => { if (typeof value !== 'string') throw new TypeError('nope'); return value; }; function StringSet(init) { if (new.target === undefined) throw new TypeError('StringSet is not a constructor'); if (init !== undefined) init = Array.from(init, test); return Reflect.construct(Set, [ init ], new.target); } Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: Object.setPrototypeOf({ add(value) { return super.add(test(value)); } }, Set.prototype).add }); Reflect.defineProperty(StringSet.prototype, Symbol.toStringTag, { configurable: true, value: 'StringSet' }); Reflect.setPrototypeOf(StringSet, Set); Reflect.setPrototypeOf(StringSet.prototype, Set.prototype); new StringSet('abc'); ``` Not that this is something one is apt to want to do normally, though it being possible does remain useful sometimes for meta/compositiony stuff. It cannot be achieved in an <= ES5 environment, but it seems all the reflection tools needed are present in environments that actually have class syntax — even, despite the awkwardness necessitated by HomeObject stuff, what is needed to employ super in methods. I’m curious if, aside from the possibility of implementation-specific things like type error messages being different, there there is anything about the above class which ends up observably different from the ES-side from one created with class syntax instead? --- Edit: I can think of one. Because of how the home object’s prototype has been set for `add` here, reassigning the prototype of `StringSet.prototype` will not affect the super reference resolution as it would in a class-syntax class.
valentinium at gmail.com (2018-07-24T02:25:09.701Z)
> That, and that the existing builtins already impose those limitations - and only class allows you to do those things, with them. I’m surprised by that statement — it appeared to me that it currently remains possible to create classes, including classes that extend built-ins, with class syntax. ``` const test = value => { if (typeof value !== 'string') throw new TypeError('nope'); return value; }; function StringSet(init) { if (new.target === undefined) throw new TypeError('StringSet is not a constructor'); if (init !== undefined) init = Array.from(init, test); return Reflect.construct(Set, [ init ], new.target); } Reflect.defineProperty(StringSet.prototype, 'add', { configurable: true, value: Object.setPrototypeOf({ add(value) { return super.add(test(value)); } }, Set.prototype).add }); Reflect.defineProperty(StringSet.prototype, Symbol.toStringTag, { configurable: true, value: 'StringSet' }); Reflect.setPrototypeOf(StringSet, Set); Reflect.setPrototypeOf(StringSet.prototype, Set.prototype); new StringSet('abc'); ``` Not that this is something one is apt to want to do normally, though it being possible does remain useful sometimes for meta/compositiony stuff. It cannot be achieved in an <= ES5 environment, but it seems all the reflection tools needed are present in environments that actually have class syntax — even, despite the awkwardness necessitated by HomeObject stuff, what is needed to employ super in methods. I’m curious if, aside from the possibility of implementation-specific things like type error messages being different, there there is anything about the above class which ends up observably different from the ES-side from one created with class syntax instead?