Concise Method Binding

Andrea Giammarchi andrea.giammarchi at gmail.com
Wed Nov 11 16:45:52 UTC 2015


The way it could work is similar to the following one:

```js

(function (wm){'use strict';

  // just to show the possible internal slot mechanism
  Object.prototype.boundTo = function (method) {
    // since I've used this for ages now in eddy.js, just replicating
    var fn = typeof method === 'function' ? method : this[method];
    var bound = wm.get(this);
    if (!bound) wm.set(this, bound = {fn:[], bound:[]});
    var i = bound.fn.indexOf(fn);
    if (i < 0) bound.bound[i = bound.fn.push(fn) - 1] = fn.bind(this);
    return bound.bound[i];
  };

}(new WeakMap));


// example
var obj = {method: function () { return this; }};

// now, whenever needed
obj.boundTo(obj.method);

// will create the slot and set it up with obj.method
// so that the following is true
obj.boundTo(obj.method) === obj.boundTo('method') &&
obj.boundTo('method')() === obj;

// if it's about another method
// the equivalent of this
::obj.anotherMethod

// whould be
obj.boundTo(anotherMethod);

```

The string fallback is not needed or relevant, it's just a semantic
shortcut in my example to reach the method through the object without
repeating the object name

Regards




On Wed, Nov 11, 2015 at 4:23 PM, JD Isaacks <jd at jisaacks.com> wrote:

> Yes your point of view is more clear now, I like this is a lot.
>
> But I do not know how that would be transpiled or what the desugared
> version would look like. However, that would be awesome as you described.
>
> A thing to note. You keep using `obj::method` which is different from
> `::object.method` the former is when method is not already attached to the
> object, the later is for then it is.
>
> An example:
>
> ```
> let foo = function(){};
> let bar = {};
>
> bar::foo // foo.bind(bar);
> ```
>
> verses
>
> ```
> let bar = { foo(){} };
>
> ::foo.bar // foo.bar.bind(foo);
> ```
>
> I think both cases theoretically would be awesome to work as you
> described. Just fuzzy on how it would look underneath.
>
> On Wed, Nov 11, 2015 at 11:14 AM, Andrea Giammarchi <
> andrea.giammarchi at gmail.com> wrote:
>
>> Yeah, I've got that, my point is that whenever you need it you just
>> `obj::method`
>>
>> Your example indeed says that currently the proposal is that
>> `obj::method` is similar to `obj.method.bind(obj)` which is indeed always
>> different and indeed you want something that makes method always the
>> same/unique bound one, which I believe is universally the preferred way.
>>
>> What are two different bound of the same method useful for? Pretty much
>> nothing, IMHO, while having a shortcut to lazily obtain a single bound
>> version of that method for that object can be useful in many ways, as
>> example `obj.on('event', anotherObj::method)` where it's always possible at
>> that point to `obj.removeListener('event', anotherObj::method)` in case its
>> needed.
>>
>> Having a shortcut that all it does is replace something already short to
>> write like a `.bind` feels to me like a missed opportunity.
>>
>> Moreover, with this improvement you won't need/care to have self-bound
>> methods at all
>>
>> ```js
>> let obj = { method(){} };
>>
>> // and whenever needed you use
>> obj::method;
>> ```
>>
>> Hope my POV is more clear now.
>>
>> Regards
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Wed, Nov 11, 2015 at 4:01 PM, JD Isaacks <jd at jisaacks.com> wrote:
>>
>>> I think what you are suggesting already exists with `::obj.method` which
>>> evaluates to `obj.method.bind(obj)`
>>>
>>> However, this creates a new function each time so `::obj.method
>>> !== ::obj.method`, not sure how `::obj.method === ::obj.method` would work.
>>>
>>> I sort of agree with you that using it that way would be preferred.
>>> However if the community wants bound methods attached to objects, there is
>>> currently no way to do that with an object literal.
>>>
>>> You would have to do something like:
>>>
>>> ```
>>> let obj = {};
>>> obj.method = function(){}.bind(obj);
>>> ```
>>>
>>> With my proposal you can.
>>>
>>> ```
>>> let obj = { ::method(){} };
>>> ```
>>>
>>>
>>>
>>>
>>> On Wed, Nov 11, 2015 at 10:20 AM, Andrea Giammarchi <
>>> andrea.giammarchi at gmail.com> wrote:
>>>
>>>> Just my thoughts, I wouldn't put any self-bound thing in the class and
>>>> rather improve that `::` proposal so that whenever you `obj::method` it
>>>> creates a uniquely bound callback so that `obj::method === obj::method` and
>>>> at that point whenever you need to export, pass, or use such method you
>>>> just `obj::method` or `obj::method()` or `let method = obj::method` and
>>>> bring the pattern whenever it's needed instead of being slightly different
>>>> per each "place" (class rather than objects)
>>>>
>>>> That would make it lazy, usable for events (in order to be able to also
>>>> remove them) and easily transpilable for smoother migration.
>>>>
>>>> Having `class A { ::method() {} }` feels like somebody is playing too
>>>> much with the protoype or "accidentally" polluting the constructor
>>>>
>>>> Regards
>>>>
>>>>
>>>> On Wed, Nov 11, 2015 at 2:50 PM, JD Isaacks <jd at jisaacks.com> wrote:
>>>>
>>>>> Andrea, Sort of. I am talking about adding an additional place where
>>>>> that operator `::` can be used -- with concise methods.
>>>>>
>>>>> Currently they cannot be used in the way I described above but I think
>>>>> there are several reasons why it makes sense.
>>>>>
>>>>> _______________________________________________
>>>>> es-discuss mailing list
>>>>> es-discuss at mozilla.org
>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151111/d5926262/attachment.html>


More information about the es-discuss mailing list