> In this example, `super.method()` will work fine, and `a.method() === 6`
because each super call will reassign `this.prop`, where `this === a`.

Did you mean `c.method() === 6`? Also I'm assuming you meant for `.method`
of `b` and `c` to have return statements too? I also assume you meant to
put `super vs getPrototypeOf` in the `c.method` too? Because, if calling
`a.method()`, then how can `super` or `getPrototypeOf` possibly refer to
`b` or`c`? `a.method() === 4`, and assuming return statements in `b` and
`c` `.method`s along with the `super vs getPrototypeOf` *after* the
assignment in `c.method` as with `b`, then `c.method() === 4`, and
`b.method() === 4`.

I believe you meant to give something more like the following example
(note, using inline methodsin all objects), which does show the problem
with the infinite recursion:

```js
example()
function example() {
    var a = {
        prop: null,
        name: 'a',
        method(){
            console.log('Setting this.prop in', this.name, super.name)
            this.prop = 4;

            // no super call here.

            return this.prop;
        },
    };

    var b = {
        __proto__: a,
        name: 'b',
        method(){
            console.log('Setting this.prop in', this.name, super.name)
            this.prop = 5;

            // super.method();
            // vs
            Object.getPrototypeOf(this).method.call(this);

            return this.prop;
        },
    };

    var c = {
        __proto__: b,
        name: 'c',
        method(){
            console.log('Setting this.prop in', this.name, super.name)
            this.prop = 6;

            // super.method();
            // vs
            Object.getPrototypeOf(this).method.call(this);

            return this.prop;
        },
    };

    c.method()
}

// Output:
// Setting this.prop in c a
// Setting this.prop in c a
// Setting this.prop in c a
// Setting this.prop in c a
// Setting this.prop in c a
​// ...repeats forever...​

```

In that example, `this` is always `c`, so each round just fires `.method`
from `b` and calls it on `c` over and over.

This is `perfectly` and `exactly` proof that `super` needs to work as
expected so we don't have to go through great lengths to make runtime-ready
(instead of declaration-only) implementations of "super" as needed in my
original two examples.

Now here's the same example using `super` instead of `getPrototypeOf`, and
it works perfectly (because everything is defined at declaration time):

```js
example()
function example() {
    var a = {
        prop: null,
        name: 'a',
        method(){
            console.log('Setting this.prop in', this.name, super.name)
            this.prop = 4;

            // no super call here.

            return this.prop;
        },
    };

    var b = {
        __proto__: a,
        name: 'b',
        method(){
            console.log('Setting this.prop in', this.name, super.name)
            this.prop = 5;

            super.method();
            // vs
            // Object.getPrototypeOf(this).method.call(this);

            return this.prop;
        },
    };

    var c = {
        __proto__: b,
        name: 'c',
        method(){
            console.log('Setting this.prop in', this.name, super.name)
            this.prop = 6;

            super.method();
            // vs
            // Object.getPrototypeOf(this).method.call(this);

            return this.prop;
        },
    };

    c.method()
}

// Output:
// Setting this.prop in c b
// Setting this.prop in c a
// Setting this.prop in c undefined
```

`super` just needs to work this way with my examples too, that's all I'm
saying, because that would be intuitive. The current behavior is not
intuitive.

I also see what you mean about `super` simply referring to
`Object.getPrototypeOf(this)` causing infinite recursion because `this` is
always the leaf-most object in the prototype chain no matter where in the
chain the method is found. Let me revise what I really meant to say:

`super` should be a reference to the prototype of the current object in the
prototype chain where the `super` statement is running from. So, at the
leaf-most object, `super === Object.getPrototypeOf(this)`. After that, in
the second-to-leaf-most object, `super ===
Object.getPrototypeOf(Object.getPrototypeOf(this))`. In the
third-to-leaf-most object `super ===
Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(this)))`.

And so on... Or, in other words, `[[HomeObject]]` for a `method()` should
just be equivalent to `o` in `o.method()` if `o` is a reference to the
current object in a prototype chain where `method()` is found. Get what I
mean?

To further prove the point that `super` doesn't work as intuitively
expected, [this comment](http://disq.us/p/67tlvb), [this comment](
http://disq.us/p/6770uc), and [this comment](http://disq.us/p/67tcgq) all
make the assumption that `super` is `Object.getPrototypeOf(this)` (which is
wrong anyways as you pointed with the infinite recursion, and I'm willing
to bet they were actually thinking more along the lines of the behavior I
just described in the last paragraph, although if super worked like that in
the first place, the source of confusion would never make itself present).
And these comments are on the very first article that I read. There are
probably other examples of confusion in comments of articles on `super`.

TLDR: `super` isn't so super, and I wish it was for the sake of clarity,
intuition, and meta-programming flexibility. My currently imagined
implementation of multiple-inheritance does not work because `super`
doesn't work the way I'm intuitively expecting due reliance on a static
[[HomeObject]] defined only during declaration.

I'm continuing to try to make my implementation work until I've exhausted
all possibilities. For reference, the following is what I wish for the API
to be like.  If anyone has any suggestion on any direction to try, it would
be much appreciated. :]

```js
import multiple from 'somewhere-yet-to-be' // multi-inheritance tool
import {DOMMatrix} from 'geometry-interfaces'

// Node, these classes do not extend anything.
class ImperativeBase {}
class TreeNode {}

// Single-inheritance:
class Transformable extends DOMMatrix {}

// Multiple-inheritance:
class Node extends multiple(ImperativeBase, TreeNode, Transformable) {}
class Scene extends multiple(ImperativeBase, TreeNode) {}
```



*/#!/*JoePea

On Tue, Jul 19, 2016 at 9:12 AM, Logan Smyth <loganfsm...@gmail.com> wrote:

> 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, /#!/JoePea <j...@trusktr.io> wrote:
>>
>>> 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 <a.d.be...@web.de> 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
>>
>>
>
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to