Scoped binding of a method to an object

Peter Seliger peter.seliger at googlemail.com
Sun Oct 13 14:01:50 PDT 2013


If you really have to live with those restriction you do describe,
there still is a low level solution working since ES 3 that keeps
the implemented codebase of certain behaviors at one place
without effecting any other code - function based traits and mixins.

One could e.g. write ones own implementations of an
Enumerable's [first], [last] accessors.


var Enumerable_first_last = (function () {

  var
    Trait,

    first = function () {
      return this[0];
    },
    last = function () {
      return this[this.length - 1];
    }
  ;

  Trait = function () {

    this.first = first;
    this.last = last;
  };

  return Trait;

}());

>From that point one is free to decide of where to apply that trait.

var
  str = "JavaScript natively supports Traits",
  arr = str.split(" "),
  coll = {
    "0": "foo",
    "1": "bar",
    "2": "baz",
    "length": 2
  }
;

It is totally fine to apply additional behavior separately to objects
that are in need of it.

Enumerable_first_last.call(arr);

arr.first(); // "JavaScript"
arr.last(); // "Traits"

Enumerable_first_last.call(coll);

coll.first(); // "foo"
coll.last(); // "bar"

One also could delegate this behavior to an objects prototype.

Enumerable_first_last.call(String.prototype);
 // works for all [[String]] implementations that do allow access via [idx]

str.first(); // "J"
str.last(); // "s"

This approach in its first step decouples implementation from
having it directly effecting a system. The second step is about
responsibility and making decisions.

Peter



On Sun, Oct 13, 2013 at 8:47 PM, Benjamin (Inglor) Gruenbaum <
inglor at gmail.com> wrote:

> > Prollyfilling is great too (perhaps you disagree?), and as its name
> suggests it happens *before* the method is added to the spec.
>
> So in your opinion adding a `.shuffle` method to an Array in a library I
> ship to users is a good idea if it makes my code clearer and nicer?
>
> I'm not saying I disagree, I'm not one of those people who passes an extra
> parameter for `undefined` in a function. I just think it can be very risky.
>
> When I have to work on big code bases that run JavaScript end to end using
> multiple frameworks and libraries on both sides, I find that extending
> object prototypes can be _very_ risky - and "Prollyfilling" (nice term by
> the way) has bitten me before. Sure, in _my_ code it can be very nice, but
> I expect libraries to have little to no side effects on my code and that's
> exactly the cases it can bite me.
>
> > How exactly did that example "fail"? The differences in detail hardly
> matter; PrototypeJS trod a cow-path that ES5 paved. Most users don't worry
> about the edge case differences.
>
> I don't think anyone today is doubting the enormous contribution
> PrototypeJS had and `.bind` was very useful in it and is very useful in
> ES5. However, running into edge cases and getting unexpected results is
> something I don't think people appreciate. The SweetJS case is just as
> interesting.
>
> There is no doubt some of the most interesting API additions have come
> from people extending natives and that says something. However, today when
> rather than writing 1000 line pages I see more and more 100 thousand lines
> code bases using multiple libraries - side effects that extending natives
> sound _very_ scary, and being able to extend the natives in a way that does
> not bite me is something I'd _really_ love to play with.
>
> > Don't worry about syntax yet.
>
> Of course, I was just toying around. Like I've said before, pretty much
> anyone else in this discussion is more qualified to come with an actual
> solution than me.
>
> > This must cost, and it does cost.
>
> Would you mind elaborating on that or linking to relevant discussion about
> the last proposal? I'd love to understand the issues involved and get a
> better understanding of the challenges something like this would bring.
>
>
>
>
> On Sun, Oct 13, 2013 at 9:37 PM, Brendan Eich <brendan at mozilla.com> wrote:
>
>> Benjamin (Inglor) Gruenbaum <mailto:inglor at gmail.com>
>>> October 13, 2013 11:00 AM
>>>
>>> Brendan Eich<brendan at mozilla.com <mailto:brendan at mozilla.com>> wrote:
>>> > No, object detection, polyfilling, and even "prollyfilling" are common
>>> and successful adaptationsp on the Web.
>>>
>>> Polyfilling is great _after_ the method has already been added to the
>>> spec.
>>>
>>
>> Prollyfilling is great too (perhaps you disagree?), and as its name
>> suggests it happens *before* the method is added to the spec.
>>
>>
>>  I'm completely fine with adding an Array.prototype.map shim to IE8, the
>>> problem with adding a method that's not on the prototype yet is that it'll
>>> fail in case the spec is different from the implementation I chose. If you
>>> mentioned PrototypeJS, its `.bind` method is one such example.
>>>
>>
>> How exactly did that example "fail"? The differences in detail hardly
>> matter; PrototypeJS trod a cow-path that ES5 paved. Most users don't worry
>> about the edge case differences.
>>
>>
>>  > Your subject recalls a defunct proposal to add lexically-scoped but
>>> heap-based -- therefore object property-lookup performance hindering --
>>> extension properties.
>>>
>>> I have to say this surprises me, a performance issue is the last thing I
>>> expected. What about attaching a prototype as a closure variable, something
>>> (and this is a syntax I __don't__ like) like:
>>> ```
>>> (function(use Array){
>>>     Array.prototype.contains = function() { ...
>>>     ...
>>>     // any code here has access to .contains, code that did not
>>> originate here does not have such access, much like a closure.
>>>     // other code is free to use Array without any collisions.
>>> })()
>>> ```
>>> Again, I __don't__ like this sort of syntax and I'm __not__ sure about
>>> the semantics here, I just noticed I have this problem - I'm probably not
>>> the most qualified for coming up with the solution out of the amazing minds
>>> right here.
>>>
>>>  Don't worry about syntax yet. The issue in any such semantic extension
>> is the required extra lookup parameter: not just contains on the right of
>> dot, but the enclosing closure scope.
>>
>> Unqualified identifiers (ones not used after dot) indeed require lookup
>> via closure environments, to the global (let's ignore 'with' and DOM inline
>> event handlers).
>>
>> Dot-qualified identifiers and equivalent bracketed computed property name
>> accesses require prototype chain lookup.
>>
>> No matter the syntax, and independent of details of how one specs it,
>> you're proposing a hybrid of the two schemes. This must cost, and it does
>> cost.
>>
>> /be
>>
>
>
> _______________________________________________
> 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/20131013/619332f2/attachment-0001.html>


More information about the es-discuss mailing list