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

/#!/JoePea joe at trusktr.io
Sat Jul 30 09:18:43 UTC 2016


> Could you not make `multiple` be a function that returns a Proxy, rather
than achieving multiple inheritance by copying properties?

​I thought about that originally, so that instead of copying methods onto
the class that extends from the multiple super classes, I would just look
for the requested properties on each of the leaf-most prototypes of each
superclass​. But there's one issue with that:  Proxy in Safari isn't
released yet. So for now, the copying that I'm doing is a temporary
workaround until I re-visit Proxy when Safari 10 comes out, and the
[`MultiClass`](
https://gist.github.com/trusktr/05b9c763ac70d7086fe3a08c2c4fb4bf#file-multiple-1-js-L38)of
my first implementation is basically where I will stick the Proxy (or just
replace MultiClass with Proxy if that's cleaner).

There are some problems though:

- I'm not sure how to handle calling the constructor of each of the
multiple sub classes if those classes are ES6 classes, as ES6 class
constructors are not callable (but that proposal is abandoned and it also
doesn't solve the problem of binding `this` -- like we can with `.call()`
on regular ES5 functions -- without requiring logic required within both
constructor definitions to be moved into a third method), so I'm [using
`new ctor()`, then copying the properties from the created objects onto the
`this` of the subclass that derives from the multiple superclasses](
https://gist.github.com/trusktr/05b9c763ac70d7086fe3a08c2c4fb4bf#file-multiple-1-js-L112-L113).
`Object.assign` may not be the best choice there, because we may need to
copy descriptors for setters/getters and Symbols too. It could work with
ES5 constructors, which are callable, but I haven't written the code to
detect ES5 constructors and use `.call()` on them. It's a rough draft, to
see what's feasible.
  - Maybe I can achieve this with `Proxy#construct` combined with
`Reflect.construct`. Hmmm...
- It's not possible to use `Proxy` on the superclass instances while they
are being constructed (if they are constructed from ES6 classes) because
the objects have to be created and returned from the constructor before a
Proxy can be applied around them. It works with ES5 classes though, by
calling the constructor with `.call(proxy)`, but the ES6 class constructors
are not callable. Is there a way?

Calling methods from the superclasses works fine, as they can simply be
bound to the `this` of the derived class instance ([I'm using `.bind()`](
https://gist.github.com/trusktr/05b9c763ac70d7086fe3a08c2c4fb4bf#file-multiple-1-js-L80-L82)
currently). If a proxied method is found with the `get` trap and bound to
`this` of the derived class, then if it reads properties on `this` then it
will end up eventually looking up the property through the Proxies on the
subclasses, so that should work.

The benefit of [this soon-to-use-actual-Proxy implementation](
https://gist.github.com/trusktr/05b9c763ac70d7086fe3a08c2c4fb4bf) is that
`super` still works because lookup happens on the original prototype chains
of the multiple superclasses, not on prototype-chain copies like in the
[other implementation where copied prototype chains are strung together](
https://gist.github.com/trusktr/8c515f7bd7436e09a4baa7a63cd7cc37). In the
strung-prototype-chains implementation `super` doesn't work because it's
not configurable without using `eval` and without accepting the limitations
of `eval` like scope loss on copied methods which is completely
unacceptable for a to-be-used-in-production implementation.

Any idea what to do about the constructor calls? Is copying properties
after the new objects are created with `new ctor()` the only way to do it,
as far as ES6 class constructors go (I can use `.call(proxy)` on the ES5
constructors)?

*/#!/*JoePea
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160730/e599fd32/attachment.html>


More information about the es-discuss mailing list