Lexically Scoped Object Extensions (was About private names)

Erik Arvidsson erik.arvidsson at gmail.com
Mon Mar 21 17:05:23 PDT 2011


On Mon, Mar 21, 2011 at 16:45, Waldemar Horwat <waldemar at google.com> wrote:
> On 03/21/11 13:13, Erik Arvidsson wrote:
>>
>> The thread about using private names is getting a bit unwieldy but I'd
>> like to focus on the  use case that I have been thinking of as
>> "Lexically scoped monkey patching" or "Lexically scoped object
>> extensions" instead of focusing on how to use "private names" to fit
>> this scenario.
>>
>> Extending built ins and modifying existing classes to work around bugs
>> or to provide a better API is (or was) a common pattern. Today a lot
>> of JS library shun this approach due to the risk of conflicts.
>>
>> Let us assume that you could extend an object in your current lexical
>> scope and that such extensions could be imported from a module into
>> your current scope.
>>
>> Given:
>>
>> {
>>   function largerThanN(obj, n) {
>>     return obj.filter(function(item) {
>>       return item>  n;
>>     }
>>   }
>>
>>   var a = [0, 1, 2, 3, 4];
>>   print(largerThanN(a, 2));
>> }
>>
>> Now we would like to make largerThanN to work with Object objects. The
>> naïve thing to do is to just to add a filter method to
>> Object.prototype. However, this might cause conflicts with other code
>> that uses objects. The idea here is that we can do this safely in our
>> scope (ignore syntax except that it is important that it can be done
>> statically).
>>
>> {
>>   extend Object.prototype with {
>>     filter: function(fun) {
>>       var retval = {};
>>       for (var key in this) {
>>         if (fun(this[key])
>>           retval[key] = this[key];
>>       }
>>       return retval;
>>     }
>>   };
>>
>>   function largerThanN(obj, n) {
>>     return obj.filter(function(item) {
>>       return item>  n;
>>     }
>>   }
>>
>>   var a = [0, 1, 2, 3, 4];
>>   print(largerThanN(a, 2));
>>   var o = {a: 0, b: 1, c: 2, d: 3, e: 4};
>>   print(largerThanN(0, 2));
>> }
>>
>> The above use case cannot be solved using private names because
>> private names conflict with public names.
>>
>> Can we agree that this is a use case that we care about and focus on
>> this instead of whether private names can or cannot do this?
>
> Yes, this is useful.  If you follow this to its logical conclusion (in
> particular, supporting Allen's use cases), you'll get something analogous to
> ES4 namespaces.

Yes, but we were hoping we could limit the scope of these
significantly so we don't end up with something like ES4 namespaces.

1) The scope of an extension is limited to a module and it is
statically determined. This needs new syntax so it can be detected
without executing any code.

2) An extension is limited to an object and a property name (sure we
would support importing * from a definition but that would still be
something that can be statically determined before any code execution)

Given these 2 we believe that we can build the alternative lookup
table for the object statically and associate that with the module
scope, making property lookups not have the explosive performance
overhead that ES4 namespaces had.



-- 
erik


More information about the es-discuss mailing list