On Oct 1, 2011, at 11:11 AM, François REMY wrote: > My code was not a fix, it was intended to show that while your first case’ > behavior was explained in the spec (super had to be null), the one of my own > case was not (ie: the interaction of ‘super’ with bind).
All well defined in the proposal Remember the |super| can be thought of as having two values depending upon the usage. When evaluated for value, it value is always the same as the this value. In a bound function the, evaluated value of super is the bound this value. The other value of super is the property lookup continuation value. That value is statically bound when the function is created (ie, installed as a method in an object). It is the value of the object's [[Prototype]] internal property. var widget = { hookup: function() { // |this| is widget >>>>>> actually depend upon how function is invoked, normal yes normally widget // |super| is widget >>>>>> no, and not null. For evaluation purposes it is the same as |this| >>>>>> the lookup continuation is Object.prototype which is the [[Prototype]] of the containing obj lit window.addEventListener('load', function(event) { // |this| is widget // |super| ?? >>>>>> for evaluation purposes it is widget (as bound by bind) >>> >>>>>> the lookup continuation is null, because it doesn't meet the "part of an object literal" criterial below : from proposal: "When a function that references super is defined as part of an object literal its [[Super]] internal property is set to the same value as the [Prototype]] internal property of the object created by the object literal. Such functions include functions defined using method property definitions, functions defined using get or set definitions, and functions defined as a MemberExpression within the AssignmentExpression of a PropertyAssignment. Functions defined outside of object literals (or class declarations) that reference super are created with their [[Super]] internal property set to null. Property accesses based off of super always perform property lookups start with the object that is the the value of the containing function’s [[Super]] internal property. If [[Super]] is null, the property lookup immediately fails and produces the value undefined." }.bind(this), false); Expressing this criteria another way, a function in an object literal only gets a non-null [[Super]] value if the function is either the immediate value of an data property or the [[Get]] or [[Set]] function of an accessor property. > > I’ve no idea of how we should solve the problem. Maybe the ‘bind’ method > should create a copy of the original function whose ‘boundThis’ is equal to > the object’s this and whose ‘super’ is equal to Object.getPrototypeOf(this). Object.defineMethod is used to rebind [[Super]] (actually creates a new function with the same code and [[Scope]] but a different [[Super]] binding). defineMethod and bind have nothing to do with each other. bind is about the value of |this| which is always the same as the value of |super|. defineMethod is about the the value of [[Super]] - the property lookup continuation point. > > function Obj() { } > Obj.prototype.getX = function() { return 10; } > > function Obj2() { Obj(this); } > Obj2.prototype = Object.create(Obj.prototype); > Obj2.prototype.getX = function() { return super.getX()+1; } [[Super]] of getX would be null. You probably want to say: Object.defineMethod( Obj2.prototype, 'getX', function () {return super.getX() + 1}; in which case [[Super]] of getX would be Obj.prototype > > var a = new Obj2(); > var b = Object.create({getX:function() { return 100; }}); > b.getX=a.getX.bind(b); I suspect what you really want to say above is Object.defineMethod(b, 'getX', a.getX).bind(b); > > assert(a.getX() == 11); yes 11 is correct > assert(a.getX() == 101); // or should it be 11? false. Or did you mean assert (b.getX() == 101) as written above, g.getX) will also be 11. this is because of the static binding of [[Super]] when the method is installed > A typical programming language would (probably) require 11, I know of no other programming language that permits something like bind to permanently fix a methods this bind or that permits a method (that references this) to be invoked without supply explicitly supplying a this value. > but then you’ve no way to solve the asynchronous pattern (super would remain > null and only this would be bound). This whole business of trying to bind this in a callback is a idiom that I think is unique to JS. In any other language, the problem would solved by using a lambda to capture whatever state the callback function need to reference: ... { //lexical block let actualWidget = this; window.addEventListener('load', function (event) { actualWidget.whatever(); //instead of this.whatEver }, false); }; ... binding this for non-method function invocations should be considered a JS antipattern. Allen > > François > > From: John J Barton > Sent: Saturday, October 01, 2011 6:16 PM > To: François REMY > Cc: Brendan Eich ; Axel Rauschmayer ; es-discuss > Subject: Re: Super-calls > > > On Sat, Oct 1, 2011 at 9:05 AM, François REMY <fremycompany_...@yahoo.fr> > wrote: > In my understanding, super would be null. > > What would be more complex is : > var widget = { > hookup: function() { > // |this| is widget > // |super| is widget > window.addEventListener('load', function(event) { > // |this| is widget > // |super| ?? > }.bind(this), false); > Unfortunately my example and your fix are both impractical. We have to bind > the function *and* save a reference to it because we don't have garbage > collection. That provides another example to try to understand super: > this.loadHandler = function(event){ > // this is widget > // Now super? > }.bind(this); > window.addEventListener('load', this.loadHandler, false); > } > }; > widget.hookup(); > jjb > _______________________________________________ > 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