Luke Hoban wrote:
In fact, without<|, are there any cases where super behaves
correctly in an object literal, other than making super calls to
Object.prototype functions?

We haven't eliminated the ability to define object literals that
inherit from objects other than Object.prototype.  We have just
changed the syntax for specifying them from: proto<| {} to
{__proto__: proto}

Good point.  Object literals with inline __proto__ declarations do
provide method contexts where super will behave correctly. But I
think it's fair to assume that most object literals will not include
inline __proto__ declarations.

In general, if you have multiple level instance based inheritance
hierarchies, super has the same general utility that it has in an a
class/instance based inheritance hierarchy.

But only if that multi-level instance hierarchy is created in a very
specific (and arguably uncommon) way.  That's my concern.  We happen
to be discussing adding a new syntactic construct for classes, and
can make sure that 'super' always works inside classes.  But we can't
make 'super' always work inside object literals.

Take Backbone/Underscore as an example.  A developer writes some
code like:

var Note = Backbone.Model.extend({
    set: function(attributes, options) {
        super.set(attributes, options);
    }
});

Of course, the above is a case where I suggest a mustache should
probably be used.

Although it isn't obvious from the code I shared, this is actually
creating a new object which has Backbone.Model in its prototype
chain, and putting a set method in the new instance.  So mustache
doesn't easily integrate into the syntax here.  One would need to
change the API model non-trivially, and the consumption syntax
somewhat significantly, to use mustache here.

In that case, it is the place for {__proto__: Backbone.Model, set: ...} or similar construct, where super is highly usable.

The issue of passing new semantic constructors into legacy
frameworks is certainly worth thinking about.  Although, i tend to
think that actively maintain frameworks will get ahead of the ES6
adoption curve.  And that legacy using a out of date framework is
much less likely to start using new ES6 constructs.

This seems optimistic, but possible.  More importantly though, do we
know how these libraries would address this sort of thing?  And what
the transition would look like (can they do it in a library-only way
such that they can feature detect to work correctly with new ES6
constructs, but still work in pre-ES6 environments)?

Of course, the above doesn't even work for ES5 since it it ignores
non-enumerable properties, doesn't copy accessor properties
correctly, and probably unintentionally includes inherited
properties. We should be cherry picking super as the only feature
that is problematic for such code. One might speculate if these
deficiencies aren't causing problems today, then perhaps the issue
of passing new language constructs into to legacy frameworks that
don't correctly deal with them is not a significant problem.

Good point.  Though one might also speculate that none of the ES5
features mentioned have seen enough adoption on the web yet to
understand the full impact of these problems.

But I think a difference that makes me more concerned about super is
that this is something these APIs are trying to do already today.
The backbone.js docs [1] that I took this example from explicitly
call out __"Brief aside on super: JavaScript does not provide a
simple way to call super — the function of the same name defined
higher on the prototype chain. If you override a core function like
set, or save, and you want to invoke the parent object's
implementation, you'll have to explicitly call it..."__.  It gets a
bit more subtle to say "JavaScript has a way to call super, but it
won't work here."

And what is your concern here? super now allows to do it right (if you don't define a method bad way - in fact Object.defineMethod is needed for programmatic definition of a method from a variable). Libraries can begin to use it.

Here is another way to think about this class of issues. super is a
language feature that is design to work at the level of the
built-in behavior composition mechanism of ES (a fixed single
inheritance [[Prototype]] chain).  _extend and other abstraction
impose a different behavioral composition model.  super may not
work as expected with those other models unless their
implementation takes it input account in their implementation.

That's a fair summary.  In practice though, a lot of object models in
JavaScript are built using these higher-level abstractions built on
top of the core JS prototype chain.  Mostly, features at the core
language level continue to be usable via these higher level
abstractions.  It's concerning to add core language features that
can't (or can't sufficiently easily) be used by the common
abstractions.

The question may be also, if those abstractions (which were filling the gap because raw prototype inheriotance was not good enough) are as badly needed now that prototype inheritance begins to be usable for much bigger crowd.

Perhaps the ultimate question is just - what is the best an existing
library developer offering a JS object model abstraction (like
extend) can do to support super?

Luke

Herby

[1] http://backbonejs.org/
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to