Scoped binding of a method to an object

Brendan Eich brendan at
Sun Oct 13 12:15:27 PDT 2013

> Benjamin (Inglor) Gruenbaum <mailto:inglor at>
> October 13, 2013 11:19 AM
> Keeping a third parameter beyond object and property name seems 
> unnecessary.

Here is a counterexample based on the strawman's syntax:

// In module LINQ's body:
   extension Array.prototype {
     where: Array.prototype.filter,
   export function query(a, w, s) {
     return a.where(w).select(s);

import {query} from "LINQ"; = () => "oops";

var b = readData();
var w = ..., s = ...;
var r = query(b, w, s);

// So far, so good. Now let's try an array-like:
var c = { length: 0 };

// and let's be mean:

Object.prototype.where = () => "oops for real!"; = x => x; // identity function

// Fill c from b and query c with w and s:
b.forEach(e => c[c.length++] = e);
var s = query(c, w, s);

// This must hold:
assertEqual(s, "oops for real!");

The only way to make this work is for the code in LINQ's body, in 
function query, to look for 'where' in 'a' (whose type is not known 
statically) by passing a token for the extended scope of module LINQ's body.

When 'a.where' is evaluated to call the method, if 'a' is an instance of 
Array.prototype with no shadowing 'where', in particular when it refers 
to 'b', then the extension method = Array.prototype.filter is found.

When 'a' refers to 'c', however, the code in LINQ does not know this _a 
priori_, so again the lookup of 'where' in c must pass the scope token. 
But this time, because c is an array-like Object instance that does not 
delegate to Array.prototype, the extension 'where' method is not found.

> In my likely naive eyes, dynamic  `this` gives us great power here. 
> Thinking about other languages that deal with the problem. As far as I 
> remember C# extension methods are just (really nice) syntactic sugar 
> for statics.

C# has static types and name lookup rules. JS has neither in full, 
although its name lookup rules are static within functions (and blocks 
in ES6), excluding 'with'.

> Is it difficult to convert something like:
> ```
> Array.prototype.last = function(){ return this[this.length-1] }
> ```
> To something like
> ```
> function Array$prototype$last(param1){ return (function(){ return 
> this[this.length-1] }).call(param1); }
> ```
> ?
You have not defined "convert", and there's no client code that calls 
'last' on a given array instance.

Another way of saying this: your name mangling does nothing to help an 
array ('b' in my example) find its method. There's no static type, no 
class or traits. The lookup in LINQ to call a.where is fully dynamic. 
Same for any use of your last method. The name rendezvous must be via 
prototypal lookup.

If you wrote client code in scope of the 'last' extension, e.g.

   var b = [1, 2, 3];

and expected some whole-program transformation (which we do not perform 
in JS, too much ambiguity -- think of computed property names, never 
mind 'with' and the global object and eval!) that results in

   var b = [1, 2, 3];
   alert((b instanceof Array) ? Array$prototype$ : b.last());

then you have essentially added the third (scope token) parameter by 
code expansion. Whether ?: or an if statement or polymorphic lookup is 
used, that's real added runtime cost, and it won't fly.

> ---------- Forwarded message ----------
> From: Erik Arvidsson <erik.arvidsson at 
> <mailto:erik.arvidsson at>>
> To: Brendan Eich <brendan at <mailto:brendan at>>
> Cc: es-discuss <es-discuss at <mailto:es-discuss at>>
> Date: Sun, 13 Oct 2013 13:32:23 -0400
> Subject: Re: Scoped binding of a method to an object
> We did proposes this back in 2011
> I wasn't at this actual F2F meeting so I don't know many details.
> Brendan might remember what the blocking issue was?

More information about the es-discuss mailing list