The `super` keyword doesn't work as it should?

classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|

The `super` keyword doesn't work as it should?

/#!/JoePea
For example, both of these examples don't work in Chrome:

```js
function A() {
    console.log('A')
}
A.prototype.constructor = A
A.prototype.hello = function() {
    return 'hello'
}

function B() {
    console.log('B')
    // super()
    A.call(this)
}
B.prototype = Object.create(A.prototype)
B.prototype.constructor = B
B.prototype.hello = function() {
    return super.hello() + 'there'
}

new B
```

and

```js
let obj1 = {
    hello() {
        return 'hello'
    },
    sayHello() {
        console.log(this.hello())
    }
}

console.log('Obj1 says hello:')
obj1.sayHello()

let obj2 = Object.create(obj1)
Object.assign(obj2, {
    hello() {
        return super.hello() + 'there.'
    }
})

console.log('Obj2 says hello:')
obj2.sayHello() // Error
```

I was hoping `super` was more flexible than that.

For example, in the first snippet, 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. It could throw an error if `.constructor` is not found, in the case of ES5-style classes that aren't defined using that pattern that ES6 classes are syntax sugar for.

And in the second example, why does `super.hello` not work as expected?

I believe that these limitations may severely limit my ability to create the multiple-inheritance tool that I'm imagining over at https://esdiscuss.org/topic/symbol-for-modifying-property-lookup#content-8.

Any ideas or suggestions?


/#!/JoePea

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

/#!/JoePea
Regarding the second example, [this resource](http://exploringjs.com/es6/ch_oop-besides-classes.html#_caveat-objectassign-doesnt-work-well-for-moving-methods) explains why `Object.assign` doesn't work as expected.

I believe the VM should be smarter than that, and let end-developers use any technique for inheritance that they wish.

For example,maybe the VM should determine at runtime what the `[[HomeObject]]` is based on what object the method is called on. Seems like that would make `super` much more useful.

Doesn't that make more sense? If not, why not?

If this were the case, then the first example would work just fine too.

/#!/JoePea

On Mon, Jul 18, 2016 at 2:00 PM, /#!/JoePea <[hidden email]> wrote:
For example, both of these examples don't work in Chrome:

```js
function A() {
    console.log('A')
}
A.prototype.constructor = A
A.prototype.hello = function() {
    return 'hello'
}

function B() {
    console.log('B')
    // super()
    A.call(this)
}
B.prototype = Object.create(A.prototype)
B.prototype.constructor = B
B.prototype.hello = function() {
    return super.hello() + 'there'
}

new B
```

and

```js
let obj1 = {
    hello() {
        return 'hello'
    },
    sayHello() {
        console.log(this.hello())
    }
}

console.log('Obj1 says hello:')
obj1.sayHello()

let obj2 = Object.create(obj1)
Object.assign(obj2, {
    hello() {
        return super.hello() + 'there.'
    }
})

console.log('Obj2 says hello:')
obj2.sayHello() // Error
```

I was hoping `super` was more flexible than that.

For example, in the first snippet, 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. It could throw an error if `.constructor` is not found, in the case of ES5-style classes that aren't defined using that pattern that ES6 classes are syntax sugar for.

And in the second example, why does `super.hello` not work as expected?

I believe that these limitations may severely limit my ability to create the multiple-inheritance tool that I'm imagining over at https://esdiscuss.org/topic/symbol-for-modifying-property-lookup#content-8.

Any ideas or suggestions?


/#!/JoePea


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Bergi
In reply to this post by /#!/JoePea
/#!/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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

/#!/JoePea
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 <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Andrea Giammarchi-2
`super === Object.getPrototypeOf(this)` also doesn't work with multiple inheritance.

If interested, it has been solved dynamically in this good'ol library:

Regards

On Tue, Jul 19, 2016 at 11:03 AM, /#!/JoePea <[hidden email]> 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 <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Logan Smyth
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 <[hidden email]> wrote:
`super === Object.getPrototypeOf(this)` also doesn't work with multiple inheritance.

If interested, it has been solved dynamically in this good'ol library:

Regards

On Tue, Jul 19, 2016 at 11:03 AM, /#!/JoePea <[hidden email]> 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 <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Raul-Sebastian Mihăilă
In reply to this post by /#!/JoePea
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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Allen Wirfs-Brock

> On Jul 19, 2016, at 11:45 AM, Raul-Sebastian Mihăilă <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Bergi
In reply to this post by Raul-Sebastian Mihăilă
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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

/#!/JoePea
In reply to this post by Logan Smyth
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 <[hidden email]> 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 <[hidden email]> wrote:
`super === Object.getPrototypeOf(this)` also doesn't work with multiple inheritance.

If interested, it has been solved dynamically in this good'ol library:

Regards

On Tue, Jul 19, 2016 at 11:03 AM, /#!/JoePea <[hidden email]> 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 <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

medikoo
Joe, see this post: http://mozilla.6506.n7.nabble.com/Making-quot-super-quot-work-outside-a-literal-td90457.html#a90551

There are some explanations there on  why super was implemented as something static and not dynamic
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Andrea Giammarchi-2
For implementation sake, this is a quick'n'dirty approach that brings a dynamically resolved `super` to any object or prototype:

Usage example:
```js
function A() {
  console.log(this.constructor.name);
}
A.prototype.method = function () {
  console.log('method from ' + this.constructor.name);
};

function B() {
  this.super();
  console.log(this.constructor.name);
}
B.prototype = Object.create(A.prototype, {constructor: {value: B}});
withSuperContext(B.prototype).method = function () {
  this.super.method();
  console.log('method from ' + this.constructor.name);
};

function C() {
  this.super();
  console.log(this.constructor.name);
}
C.prototype = withSuperContext(
  Object.create(B.prototype, {constructor: {value: C}})
);
C.prototype.method = function () {
  this.super.method();
  console.log('method from ' + this.constructor.name);
};

var c = new C;
// will log
// A
// B
// C

c.method();
// method from A
// method from B
// method from C

```

Best Regards


On Wed, Jul 20, 2016 at 9:06 AM, medikoo <[hidden email]> wrote:
Joe, see this post:
http://mozilla.6506.n7.nabble.com/Making-quot-super-quot-work-outside-a-literal-td90457.html#a90551

There are some explanations there on  why super was implemented as something
/static/ and not /dynamic/



--
View this message in context: http://mozilla.6506.n7.nabble.com/The-super-keyword-doesn-t-work-as-it-should-tp357032p357113.html
Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Logan Smyth
Joe, yes sorry, my mistake. `a` should have `__proto__: b`, and `b` should have `__proto__: c` in my example, that's what I get for not validating it better. Each could `return` but since `a.method` was the only one I called, it was the only one I put the `return` in.

On Wed, Jul 20, 2016 at 3:27 AM, Andrea Giammarchi <[hidden email]> wrote:
For implementation sake, this is a quick'n'dirty approach that brings a dynamically resolved `super` to any object or prototype:

Usage example:
```js
function A() {
  console.log(this.constructor.name);
}
A.prototype.method = function () {
  console.log('method from ' + this.constructor.name);
};

function B() {
  this.super();
  console.log(this.constructor.name);
}
B.prototype = Object.create(A.prototype, {constructor: {value: B}});
withSuperContext(B.prototype).method = function () {
  this.super.method();
  console.log('method from ' + this.constructor.name);
};

function C() {
  this.super();
  console.log(this.constructor.name);
}
C.prototype = withSuperContext(
  Object.create(B.prototype, {constructor: {value: C}})
);
C.prototype.method = function () {
  this.super.method();
  console.log('method from ' + this.constructor.name);
};

var c = new C;
// will log
// A
// B
// C

c.method();
// method from A
// method from B
// method from C

```

Best Regards


On Wed, Jul 20, 2016 at 9:06 AM, medikoo <[hidden email]> wrote:
Joe, see this post:
http://mozilla.6506.n7.nabble.com/Making-quot-super-quot-work-outside-a-literal-td90457.html#a90551

There are some explanations there on  why super was implemented as something
/static/ and not /dynamic/



--
View this message in context: http://mozilla.6506.n7.nabble.com/The-super-keyword-doesn-t-work-as-it-should-tp357032p357113.html
Sent from the Mozilla - ECMAScript 4 discussion mailing list archive at Nabble.com.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

/#!/JoePea
@medikoo, wow, the conversation has been going on for a long time. And in that conversation you linked, Sean Eagan said

> I think a static |super| in light of ​ ​ES's dynamic |this| would actually be much more​ ​surprising.  This would lead to looking for properties in a static |super| object that may be​ ​completely unrelated to the dynamic |this| value of a given function activation, which would​ ​certainly be surprising.
> Consistency with other languages is valuable, but consistency with this language (ES) is vital.  A static |super| would be inconsistent with ES's dynamic |this|.

​I couldn't agree more.​
​ ​

The interesting thing is although the conversation is so old, `super` is only just now coming out in JS engines. I only just now discovered this undesirable behavior because ES6 only just now became reality.

Is there any hard evidence of the performance cost of a dynamic super? So far I've read in various places (for example the thread linked to by @medikoo, Axel's 2ality article on super) about there being "overhead", but the articles haven't quantified or put into perspective the actual performance cost. Is it really that bad?

/#!/JoePea

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

medikoo
/#!/JoePea wrote
Is there any hard evidence of the performance cost of a dynamic super? So
far I've read in various places (for example the thread linked to by
@medikoo, Axel's 2ality article on super) about there being "overhead", but
the articles haven't quantified or put into perspective the actual
performance cost. Is it really that bad?
Adding any additional internal property for function that needs to be updated depending on circumstances, definitely will bring noticeable performance regression, and no-one would want to agree for that.

Still, for me (at least now) it's not clear why it actually implies any cost (?) If dynamic, the super should bring not cost, as in clear thinking it's just pure keyword which forces no action/calculation from compiler/interpreter until the moment it's evaluated. It'll be great if someone clarifies that.
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Claude Pache
In reply to this post by /#!/JoePea
There is probably no way to make the `super` semantics just work in all use cases. But I think that the choice made in ES6 is the right one in order to have it correctly working in the most naïve (and maybe the most common?) use cases of method borrowing, i.e., when you don’t have knowledge of — or even you wilfully ignore — its implementation details. Consider for example:

```js
class MyArray extends Array {
    forEach(callback, thisArg) {
        // ...
        super.forEach(callback, thisArg)
        // ...
    }
}
```

and somewhere else:

```js
NodeList.prototype.forEach = MyArray.prototype.forEach // or: (new MyArray).forEach

HTMLCollection.prototype.forEach = MyArray.prototype.forEach
```

Here, I expect that `super.forEach` will continue to point to `Array.prototype.forEach`. This is because I’m thinking of `MyArray.prototype.forEach` as a black box that should not change its behaviour just because I’m moving it around, as it is generally the case with methods of the builtin library.

—Claude
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

/#!/JoePea
It doesn't make sense because then `super` isn't really referring to the super class that the method is used on. I think it makes more sense for `super` to take meaning depending on where the method is found, not where it is defined.

What if there was also something like `Function.prototype.bind` like `Function.prototype.with`, so `someFunc.with(homeObject)` returns a new function who's [[HomeObject]] is the specified `homeObject`. It would be possible to do `someFunc.with(...).bind(...)` to configure both the home object and `this`.

/#!/JoePea

On Thu, Jul 21, 2016 at 3:21 AM, Claude Pache <[hidden email]> wrote:
There is probably no way to make the `super` semantics just work in all use cases. But I think that the choice made in ES6 is the right one in order to have it correctly working in the most naïve (and maybe the most common?) use cases of method borrowing, i.e., when you don’t have knowledge of — or even you wilfully ignore — its implementation details. Consider for example:

```js
class MyArray extends Array {
    forEach(callback, thisArg) {
        // ...
        super.forEach(callback, thisArg)
        // ...
    }
}
```

and somewhere else:

```js
NodeList.prototype.forEach = MyArray.prototype.forEach // or: (new MyArray).forEach

HTMLCollection.prototype.forEach = MyArray.prototype.forEach
```

Here, I expect that `super.forEach` will continue to point to `Array.prototype.forEach`. This is because I’m thinking of `MyArray.prototype.forEach` as a black box that should not change its behaviour just because I’m moving it around, as it is generally the case with methods of the builtin library.

—Claude


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

Allen Wirfs-Brock

On Jul 24, 2016, at 7:04 PM, /#!/JoePea <[hidden email]> wrote:

What if there was also something like `Function.prototype.bind` like `Function.prototype.with`, so `someFunc.with(homeObject)` returns a new function who's [[HomeObject]] is the specified `homeObject`. It would be possible to do `someFunc.with(...).bind(...)` to configure both the home object and `this`.


This was  included in the ES6 drafst for quite awhile. Initially with the name defineMethod and latter as toMethod.  But it was eventually decided to remove it.  The pros and cons of such a function were extensively discussed with in TC39 over a several year period. For example,  see https://github.com/tc39/tc39-notes/blob/master/es6/2014-01/jan-28.md#more-on-tomethod 


Where it has been left by TC30 is roughly:
1) There are indeed use cases for dynamically configuring the HomeObject binding but they are quite specialized.
2) All of the solution that have been proposed are confusing or error prone.
3) So far, the actual user demand for such a feature is small.
4) We aren’t going to do anything until there is significant real world feedback saying that it really is needed.

Allen 

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

/#!/JoePea
1) There are indeed use cases for dynamically configuring the HomeObject binding but they are quite specialized

I suppose my case is quite specialized. I am wanting to duplicate the prototype chains of ES6 classes, but I have no reliable (afaik) way to make the `super` keyword work on copied methods. If I copy the method by reference then the `super` keyword is based on the wrong `HomeObject`. If I copy the method by getting its the source with `.toString()` followed by using `eval` to define the new method on an object initialization, that works and `super` will work, but this has problems if the original method relied on variables in the outer scope where it was originally defined as the copied method will not have access to that scope (f.e. code transpiled by Babel may not be able to see the Babel helper functions). 

I am trying to implement a function `multiple()` so that I can do

```js
class SomeClass { ... }
class
​OtherClass​
 { ... }
class Foo extends multiple(SomeClass, OtherClass) { ... }
```

and it's proving to be really difficult because I can't configure `HomeObject`. The `multiple` function copies the prototype chains of each class, then combines them together (when possible, otherwise an error is thrown, depending on the native prototypes involved). As mentioned, this somewhat works using `eval()` in the implementation, except that copied methods don't work if they rely on variables of the outer scope where they were originally defined. For example, suppose `SomeClass` in the following example was imported from another file, and it depends on Babel helpers defined in the original scope where it was imported from:

```js
import SomeClass from './somewhere/SomeClass'
class 
​OtherClass​
 { ... }
class Foo extends multiple(SomeClass, OtherClass) { ... }
```

The `multiple()` call will copy the methods of `SomeClass` onto a new prototype chain (the methods need new `HomeObjects`), but the new methods will fail to reference anything from the original scope where `SomeClass` came from.

I need to be able to modify `HomeObject`s without using an `eval()` hack in order for my `multiple()` implementation to work 100% as intended.

For now I may need to abandon my effort and use class-factory "mixins" as in

```js
let SomeMixin = baseClass => class SomeMixin extends baseClass { ... }
```

, but the downside of this is that the classes are not usable as standalone classes, so and end-user can't do

```js
class Foo extends SomeClass { ... }
```

We are required to do

```js
class Foo extends SomeClass(null) { ... }
```

 but due to the `null` the class we won't have `Object` methods. We could do

```js
class Foo extends SomeClass(Object) { ... }
```

, but that is not also ideal as `Object` is not guaranteed to be the native Object; `window.Object` could be overridden.

I really want to define plain ES6 classes and use 3rd party plain ES6 classes (not class factories). It means that those classes are not limited to being used as mixins.

For reference, here's the implementation so far (with the ugly caveats of cloning methods with `eval`): https://gist.github.com/trusktr/8c515f7bd7436e09a4baa7a63cd7cc37

I was planning to add caching so that combinations of classes could be re-used (similar to what [mixwith.js](https://github.com/justinfagnani/mixwith.js) does to cache mixin applications).

> We aren’t going to do anything until there is significant real world feedback saying that it really is needed.

Here's that feedback. :D

TLDR, it seems that without flexibility in modifying `[[HomeObject]]` in order to control what `super` references, I cannot implement an ideal `multiple()`-inheritance helper that I would be able to comfortably suggest for use in a production app. I would definitely not recommend the my `eval`-based implementation as it will fail in ways that are very undesirable and unexpected.

With the limitation of a static `super`, I can't do something simple like use `Object.assign` to simply copy some methods from one class' prototype onto the class where I need them. That's normal pre-ES6 stuff that has worked along with a dynamic `this` since forever, so the change in behavior from `this` to `super` doesn't fit with the pre-ES6 language that we are previously accustomed to and that we love (I do). ES6+ is backwards-incompatible with some pre-ES6 paradigms.

Pleeeease, let's add something like `toMethod`, or make `super` dynamic (preferably both). I don't see any downside to having something like `Function.prototype.toMethod`, as it is an opt-in type of feature, so it won't bring with it performance loss like a dynamic `super` might (I still haven't heard conclusive evidence regarding those performance losses).

From what I can imagine, property lookup checks checks the current object, then goes to the next prototype and does the same, until finally it reaches a prototype where the property is found. Once that object (a HomeObject) is found, we know what the `HomeObject` is. It seems very easy to call a found method with that found `HomeObject`argument, and when the method is called and if it uses `super`, then a similar search will happen up the prototype chain until the matching super property is found. The second prototype search (the one initiated due to the method using `super`) is already a requirement, so, this means that the extra overhead for a dynamic `super` stems from simply passing as argument the `HomeObject` of a method once the method is found on a prototype chain. A static super means that the `[[HomeObject]]` variable is simply defined forever instead of  being marked in the property-lookup of a method, and that doesn't seem like tons of extra overhead. Note that the property lookup is going to happen anyways, so why not mark the `HomeObject` during the property lookup algorithm?

*Is that really enough overhead to merit a static `super`?* If someone can explain it (or link to it), that would be greatly appreciated.

I also think having dynamic `super` (or at least a way to configure it) opens up language possibilities that can make interesting things happen (for example, my `multiple()`-inheritance implementation would work smoothly and instanceof checks would also work thanks to `@@hasInstance`). The mere fact that a dynamic or configurable `[[HomeObject]]` would allow for the creation of a tool like what I am trying to implement is good enough reason to have the feature. Who knows what other awesome ideas people will come up with.

/#!/JoePea

On Sun, Jul 24, 2016 at 7:54 PM, Allen Wirfs-Brock <[hidden email]> wrote:

On Jul 24, 2016, at 7:04 PM, /#!/JoePea <[hidden email]> wrote:

What if there was also something like `Function.prototype.bind` like `Function.prototype.with`, so `someFunc.with(homeObject)` returns a new function who's [[HomeObject]] is the specified `homeObject`. It would be possible to do `someFunc.with(...).bind(...)` to configure both the home object and `this`.


This was  included in the ES6 drafst for quite awhile. Initially with the name defineMethod and latter as toMethod.  But it was eventually decided to remove it.  The pros and cons of such a function were extensively discussed with in TC39 over a several year period. For example,  see https://github.com/tc39/tc39-notes/blob/master/es6/2014-01/jan-28.md#more-on-tomethod 


Where it has been left by TC30 is roughly:
1) There are indeed use cases for dynamically configuring the HomeObject binding but they are quite specialized.
2) All of the solution that have been proposed are confusing or error prone.
3) So far, the actual user demand for such a feature is small.
4) We aren’t going to do anything until there is significant real world feedback saying that it really is needed.

Allen 


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: The `super` keyword doesn't work as it should?

/#!/JoePea
For now, I've settled with writing classes like this:

```js
const SomeClassMixin = base => {
    class SomeClass extends base {
        // ...
    }

    return SomeClass
}

const SomeClass = SomeClassMixin(class{})
SomeClass.mixin = SomeClassMixin

export {SomeClass as default}
```

This makes it possible for an end user to import the class and extend from it like normal:

```js
import SomeClass from './SomeClass'

class OtherClass extends SomeClass {
    // ...
}
```

But, it also allows and end user to use it as a mixin:

```js
import SomeClass from './SomeClass'
import AnotherClass from './AnotherClass'

class OtherClass extends SomeClass.mixin(AnotherClass) {
    // ...
}
```

This has two main downsides:

- The class creator has to write the class as a class-factory mixin, then remember to export the mixin application on a plain `class {}`
- It is not possible to pass specific arguments to the constructors of each class.

One of my implementations of `multiple()` *does* allow one to pass arguments to each constructor. I'll re-visit that when Proxy is supported in Safari.

I can't think of any way to make this work using a class helper library, because those need to create prototype chains, and thus `super` cannot be modified unless using `eval`, in which case original scope is lost.

I literally think that a dynamic `super` and/or `Function.prototype.toMethod` would allow me to implement the ideal solution, which would have the following benefits:

I am going to leave this alone for now, and just continue with the class-factory mixin approach, although that is not my ideal solution.

Any ideas or suggestions?

/#!/JoePea

On Wed, Jul 27, 2016 at 7:51 PM, /#!/JoePea <[hidden email]> wrote:
1) There are indeed use cases for dynamically configuring the HomeObject binding but they are quite specialized

I suppose my case is quite specialized. I am wanting to duplicate the prototype chains of ES6 classes, but I have no reliable (afaik) way to make the `super` keyword work on copied methods. If I copy the method by reference then the `super` keyword is based on the wrong `HomeObject`. If I copy the method by getting its the source with `.toString()` followed by using `eval` to define the new method on an object initialization, that works and `super` will work, but this has problems if the original method relied on variables in the outer scope where it was originally defined as the copied method will not have access to that scope (f.e. code transpiled by Babel may not be able to see the Babel helper functions). 

I am trying to implement a function `multiple()` so that I can do

```js
class SomeClass { ... }
class
​OtherClass​
 { ... }
class Foo extends multiple(SomeClass, OtherClass) { ... }
```

and it's proving to be really difficult because I can't configure `HomeObject`. The `multiple` function copies the prototype chains of each class, then combines them together (when possible, otherwise an error is thrown, depending on the native prototypes involved). As mentioned, this somewhat works using `eval()` in the implementation, except that copied methods don't work if they rely on variables of the outer scope where they were originally defined. For example, suppose `SomeClass` in the following example was imported from another file, and it depends on Babel helpers defined in the original scope where it was imported from:

```js
import SomeClass from './somewhere/SomeClass'
class 
​OtherClass​
 { ... }
class Foo extends multiple(SomeClass, OtherClass) { ... }
```

The `multiple()` call will copy the methods of `SomeClass` onto a new prototype chain (the methods need new `HomeObjects`), but the new methods will fail to reference anything from the original scope where `SomeClass` came from.

I need to be able to modify `HomeObject`s without using an `eval()` hack in order for my `multiple()` implementation to work 100% as intended.

For now I may need to abandon my effort and use class-factory "mixins" as in

```js
let SomeMixin = baseClass => class SomeMixin extends baseClass { ... }
```

, but the downside of this is that the classes are not usable as standalone classes, so and end-user can't do

```js
class Foo extends SomeClass { ... }
```

We are required to do

```js
class Foo extends SomeClass(null) { ... }
```

 but due to the `null` the class we won't have `Object` methods. We could do

```js
class Foo extends SomeClass(Object) { ... }
```

, but that is not also ideal as `Object` is not guaranteed to be the native Object; `window.Object` could be overridden.

I really want to define plain ES6 classes and use 3rd party plain ES6 classes (not class factories). It means that those classes are not limited to being used as mixins.

For reference, here's the implementation so far (with the ugly caveats of cloning methods with `eval`): https://gist.github.com/trusktr/8c515f7bd7436e09a4baa7a63cd7cc37

I was planning to add caching so that combinations of classes could be re-used (similar to what [mixwith.js](https://github.com/justinfagnani/mixwith.js) does to cache mixin applications).

> We aren’t going to do anything until there is significant real world feedback saying that it really is needed.

Here's that feedback. :D

TLDR, it seems that without flexibility in modifying `[[HomeObject]]` in order to control what `super` references, I cannot implement an ideal `multiple()`-inheritance helper that I would be able to comfortably suggest for use in a production app. I would definitely not recommend the my `eval`-based implementation as it will fail in ways that are very undesirable and unexpected.

With the limitation of a static `super`, I can't do something simple like use `Object.assign` to simply copy some methods from one class' prototype onto the class where I need them. That's normal pre-ES6 stuff that has worked along with a dynamic `this` since forever, so the change in behavior from `this` to `super` doesn't fit with the pre-ES6 language that we are previously accustomed to and that we love (I do). ES6+ is backwards-incompatible with some pre-ES6 paradigms.

Pleeeease, let's add something like `toMethod`, or make `super` dynamic (preferably both). I don't see any downside to having something like `Function.prototype.toMethod`, as it is an opt-in type of feature, so it won't bring with it performance loss like a dynamic `super` might (I still haven't heard conclusive evidence regarding those performance losses).

From what I can imagine, property lookup checks checks the current object, then goes to the next prototype and does the same, until finally it reaches a prototype where the property is found. Once that object (a HomeObject) is found, we know what the `HomeObject` is. It seems very easy to call a found method with that found `HomeObject`argument, and when the method is called and if it uses `super`, then a similar search will happen up the prototype chain until the matching super property is found. The second prototype search (the one initiated due to the method using `super`) is already a requirement, so, this means that the extra overhead for a dynamic `super` stems from simply passing as argument the `HomeObject` of a method once the method is found on a prototype chain. A static super means that the `[[HomeObject]]` variable is simply defined forever instead of  being marked in the property-lookup of a method, and that doesn't seem like tons of extra overhead. Note that the property lookup is going to happen anyways, so why not mark the `HomeObject` during the property lookup algorithm?

*Is that really enough overhead to merit a static `super`?* If someone can explain it (or link to it), that would be greatly appreciated.

I also think having dynamic `super` (or at least a way to configure it) opens up language possibilities that can make interesting things happen (for example, my `multiple()`-inheritance implementation would work smoothly and instanceof checks would also work thanks to `@@hasInstance`). The mere fact that a dynamic or configurable `[[HomeObject]]` would allow for the creation of a tool like what I am trying to implement is good enough reason to have the feature. Who knows what other awesome ideas people will come up with.

/#!/JoePea

On Sun, Jul 24, 2016 at 7:54 PM, Allen Wirfs-Brock <[hidden email]> wrote:

On Jul 24, 2016, at 7:04 PM, /#!/JoePea <[hidden email]> wrote:

What if there was also something like `Function.prototype.bind` like `Function.prototype.with`, so `someFunc.with(homeObject)` returns a new function who's [[HomeObject]] is the specified `homeObject`. It would be possible to do `someFunc.with(...).bind(...)` to configure both the home object and `this`.


This was  included in the ES6 drafst for quite awhile. Initially with the name defineMethod and latter as toMethod.  But it was eventually decided to remove it.  The pros and cons of such a function were extensively discussed with in TC39 over a several year period. For example,  see https://github.com/tc39/tc39-notes/blob/master/es6/2014-01/jan-28.md#more-on-tomethod 


Where it has been left by TC30 is roughly:
1) There are indeed use cases for dynamically configuring the HomeObject binding but they are quite specialized.
2) All of the solution that have been proposed are confusing or error prone.
3) So far, the actual user demand for such a feature is small.
4) We aren’t going to do anything until there is significant real world feedback saying that it really is needed.

Allen 



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12