>>  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.

> If extend did not explicitly deal with rebinding super referencing methods 
> (which it can't, if we eliminate defineMethod) then the set method would 
> throw when it tried to invoke the super.set.  So, the code fails with an 
> exception rather than silently working incorrectly.

That is at least better - but late errors trying to use a 1st class piece of 
syntax in a seemingly meaningful location feels concerning.

> Also, a very similar issue will apply to if the argument to extend had any 
> private name properties.  So this isn't a problem that is specific to super. 
> I can actually envision how it may be easier for a built-in extend function 
> to handle super rebinding than it would be for it to handle private names.  I 
> don't currently see how a non-built-in Es<=5 semantics based extend could 
> handle it.

That's a good point, and does lead me to be concerned about the behaviour of 
ES3-style extend on private names as well.  For similar reasons, I expect devs 
will just assume this sort of thing works.

> 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."   

> 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.

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

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

Reply via email to