Re: The `super` keyword doesn't work as it should?
Raul-Sebastian Mihăilă wrote: An alternative would be to consider the object where the method key was found as the home object of the method. That's just as error-prone, method borrowing would only work when the two objects had the same superclass. Also, what about methods that are not "found" anywhere when called, for example when used with `call`/`apply`/`bind`? Or static class methods that don't use `this` at all and are called like a plain function? Are you suggesting that every property access that yields a function implicitly creates a closure over the "home"/"found" object? That's a no-no for obvious reasons. Kind regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The `super` keyword doesn't work as it should?
> On Jul 19, 2016, at 11:45 AM, Raul-Sebastian Mihăilă> wrote: > > An alternative would be to consider the object where the method key was found > as the home object of the method. that was considered while designing ES6. The problem is that it introduces an additional implicit parameter (or equivalent overhead) for every method call, regardless of whether or not it is actually needed by the invoked method. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The `super` keyword doesn't work as it should?
An alternative would be to consider the object where the method key was found as the home object of the method. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The `super` keyword doesn't work as it should?
Joe, it seems like you've focused on `super === Object.getPrototypeOf(this)` as the overall ideal without considering the issues with it. I've tried to put together a few counterexamples below. Say you have a base set up like this: ``` var a = { prop: null, method(){ this.prop = 4; // super.method(); // vs // Object.getPrototypeOf(this).method.call(this); return this.prop; }, }; var b = { __proto__: a, method: function(){ this.prop = 5; // super.method(); // vs // Object.getPrototypeOf(this).method.call(this); }, }; var c = { __proto__: b, method: function(){ this.prop = 6; }, }; ``` In this example, `super.method()` will work fine, and `a.method() === 6` because each super call will reassign `this.prop`, where `this === a`. `Object.getPrototypeOf(this)` has one main core issue here, which is that we are doing `.call(this);`, meaning that when `a.method()` is called and subsequently calls `b.method`, `this === a`, not `this === b` inside `b.method`. This means that when `b` attempts to call _its_ super class, it has no way of finding `c`, because `this === a` and `Object.getProtoypeOf(this) === b`, not `c`. This leads to the infinite recursion case that Bergi mentioned. The only way for this to work, given your proposal, would be to call `b.method` with `this === b` instead of `this === a`, e.g. ` Object.getPrototypeOf(this).method.call(Object.getPrototypeOf(this));`, but that would mean that operations happening inside `b.method`, like the `this.prop = 5;` would be assigning a property on the wrong object (`b`), instead of the `a` object, leading to `a.method() === 4`. ES6 solves this by looking up the parent prototype using the `[[HomeObject]]` as the root instead of `this`, where `[[HomeObject]]` is essentially the object that the function was attached to syntactically. The issue is that a standalone function has no object that it is attached to. This means that usage of `super.foo` ends up being restricted to only functions written with method syntax, where they are attached clearly to a specific object. On Tue, Jul 19, 2016 at 3:13 AM, Andrea Giammarchi < andrea.giammar...@gmail.com> wrote: > `super === Object.getPrototypeOf(this)` also doesn't work with multiple > inheritance. > > If interested, it has been solved dynamically in this good'ol library: > https://github.com/WebReflection/es-class#es6-ready > > Regards > > On Tue, Jul 19, 2016 at 11:03 AM, /#!/JoePeawrote: > >> Hi Bergi, yes, so the object that `super` references would work like >> `this`, where the value is determined at runtime instead of in a >> declaration. Basically, `super === Object.getPrototypeOf(this)` would >> actually be true in my examples. It may be due to ["extra overhead"]( >> http://disq.us/p/1a56gxj) that `[[HomeObject]]` is only defined during >> declaration, but that is at the huge expense of making the language less >> intuitive and also more difficult to work with in some cases (for example, >> in designing a multiple-inheritance scheme). >> >> It would simply be great for super to just work as expected in the >> examples I gave, which would mean that super would work in tandem and >> intuitively with the various ways in which we can create >> objects-extending-objects in JS. >> >> Good news is that making the necessary change to `super` in ES8 or later >> is completely backwards compatible with how it currently works. >> >> I wonder what the performance problems are and if they can be solved. >> >> */#!/*JoePea >> >> On Mon, Jul 18, 2016 at 2:46 PM, Bergi wrote: >> >>> /#!/JoePea wrote: >>> >>> Why can't `super` simply be a shortcut for "look up the prototype of the object that the method is called on, then find the `.constructor` property and call it on `this`"? That seems to be simple. >>> >>> Simple, yes, and broken in the case of multi-level inheritance: >>> ``` >>> const x = Object.assign(Object.create({ >>> method() { >>> console.log("parent"); >>> } >>> }), { >>> method() { >>> console.log("child"); >>> Object.getPrototypeOf(this).method(); // super.method() >>> } >>> }); >>> x.method(); // works as expected >>> >>> const y = Object.create(x); >>> y.method(); // infinite loop/stack overflow >>> ``` >>> A `super` query must not depend on `this` (only), it must statically >>> resolve the object on which the called method is defined. >>> >>> In constructors, using the prototype of the currenctly called >>> constructor for `super()` works well, but you'd need to use >>> `Object.setPrototype` as there is currently no declarative way other than >>> `class`es to define functions with custom prototypes. >>> >>> In methods, there would need to be a way to populate the [[HomeObject]] >>> other than declaring the method as part of a class/object literal. >>> >>> Kind regards, >>> Bergi >>>
Re: The `super` keyword doesn't work as it should?
`super === Object.getPrototypeOf(this)` also doesn't work with multiple inheritance. If interested, it has been solved dynamically in this good'ol library: https://github.com/WebReflection/es-class#es6-ready Regards On Tue, Jul 19, 2016 at 11:03 AM, /#!/JoePeawrote: > Hi Bergi, yes, so the object that `super` references would work like > `this`, where the value is determined at runtime instead of in a > declaration. Basically, `super === Object.getPrototypeOf(this)` would > actually be true in my examples. It may be due to ["extra overhead"]( > http://disq.us/p/1a56gxj) that `[[HomeObject]]` is only defined during > declaration, but that is at the huge expense of making the language less > intuitive and also more difficult to work with in some cases (for example, > in designing a multiple-inheritance scheme). > > It would simply be great for super to just work as expected in the > examples I gave, which would mean that super would work in tandem and > intuitively with the various ways in which we can create > objects-extending-objects in JS. > > Good news is that making the necessary change to `super` in ES8 or later > is completely backwards compatible with how it currently works. > > I wonder what the performance problems are and if they can be solved. > > */#!/*JoePea > > On Mon, Jul 18, 2016 at 2:46 PM, Bergi wrote: > >> /#!/JoePea wrote: >> >> Why can't `super` simply be a shortcut >>> for "look up the prototype of the object that the method is called on, >>> then >>> find the `.constructor` property and call it on `this`"? That seems to be >>> simple. >>> >> >> Simple, yes, and broken in the case of multi-level inheritance: >> ``` >> const x = Object.assign(Object.create({ >> method() { >> console.log("parent"); >> } >> }), { >> method() { >> console.log("child"); >> Object.getPrototypeOf(this).method(); // super.method() >> } >> }); >> x.method(); // works as expected >> >> const y = Object.create(x); >> y.method(); // infinite loop/stack overflow >> ``` >> A `super` query must not depend on `this` (only), it must statically >> resolve the object on which the called method is defined. >> >> In constructors, using the prototype of the currenctly called constructor >> for `super()` works well, but you'd need to use `Object.setPrototype` as >> there is currently no declarative way other than `class`es to define >> functions with custom prototypes. >> >> In methods, there would need to be a way to populate the [[HomeObject]] >> other than declaring the method as part of a class/object literal. >> >> Kind regards, >> Bergi >> ___ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The `super` keyword doesn't work as it should?
Hi Bergi, yes, so the object that `super` references would work like `this`, where the value is determined at runtime instead of in a declaration. Basically, `super === Object.getPrototypeOf(this)` would actually be true in my examples. It may be due to ["extra overhead"]( http://disq.us/p/1a56gxj) that `[[HomeObject]]` is only defined during declaration, but that is at the huge expense of making the language less intuitive and also more difficult to work with in some cases (for example, in designing a multiple-inheritance scheme). It would simply be great for super to just work as expected in the examples I gave, which would mean that super would work in tandem and intuitively with the various ways in which we can create objects-extending-objects in JS. Good news is that making the necessary change to `super` in ES8 or later is completely backwards compatible with how it currently works. I wonder what the performance problems are and if they can be solved. */#!/*JoePea On Mon, Jul 18, 2016 at 2:46 PM, Bergiwrote: > /#!/JoePea wrote: > > Why can't `super` simply be a shortcut >> for "look up the prototype of the object that the method is called on, >> then >> find the `.constructor` property and call it on `this`"? That seems to be >> simple. >> > > Simple, yes, and broken in the case of multi-level inheritance: > ``` > const x = Object.assign(Object.create({ > method() { > console.log("parent"); > } > }), { > method() { > console.log("child"); > Object.getPrototypeOf(this).method(); // super.method() > } > }); > x.method(); // works as expected > > const y = Object.create(x); > y.method(); // infinite loop/stack overflow > ``` > A `super` query must not depend on `this` (only), it must statically > resolve the object on which the called method is defined. > > In constructors, using the prototype of the currenctly called constructor > for `super()` works well, but you'd need to use `Object.setPrototype` as > there is currently no declarative way other than `class`es to define > functions with custom prototypes. > > In methods, there would need to be a way to populate the [[HomeObject]] > other than declaring the method as part of a class/object literal. > > Kind regards, > Bergi > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss