Function.prototype.bind

Brendan Eich brendan at mozilla.org
Wed Sep 10 11:03:18 PDT 2008


On Sep 10, 2008, at 10:15 AM, David-Sarah Hopwood wrote:

> However, unlike what I proposed, 'strawman:lexical_scope' doesn't make
> the bindings of the primordials that are visible when it is active
> deeply immutable. I suppose that's difficult if you want the
> prototypes to appear to be the same between code that is in such a
> block and code that is not -- for instance, '"" instanceof String'
> should work whether or not 'String' refers to a deeply immutable or
> mutable constructor.

Right. Also, people mutate standard objects, whether it's a good idea  
in the large or not. The "use lexical scope" idea is not meant to  
break compatibility on that point.

It's rarer (although still done -- see ) for web JS to mutate the  
global bindings for Object, Date, etc.


>
>> The Harmony reference implementation work is very likely to cut  
>> back the
>> old ES4 RI to ES3 and go forward from there. To avoid hijacking  
>> built-in
>> behavior it needs something like the "use lexical scope" pragma.
>
> So, is this a valid self-hosting specification of bind?
>
>   (function() {
>     use lexical scope;
>
>     Function.prototype.bind = function(self, var_args) {
>       const thisFunc = this;
>       const leftArgs = Array.slice(arguments, 1);
>       return function(var_args) {
>         const args = leftArgs.concat(Array.slice(arguments, 0));
>         return Function.apply(thisFunc, self, args);
>       };
>     };
>   )();
>
> Note that this isn't useful for ES3.1 unless 'use lexical scope' is
> added to ES3.1 (or implied by ES3.1-strict).

It's close (saw your followup) but:

1. It does not make Function.prototype.bind non-enumerable.

2. It's vulnerable to mutations of Array.slice,  
Array.prototype.concat, and Function.apply.

1 is fixable using ES3.1's Object.defineProperty in the self-hosted  
reference implementation.

2 is a wider problem, which could be addressed in ES3.1 by freezing  
certain standard constructors.

But that's again woefully incompatbile: you can't freeze the self- 
hosted Array and have it be used as real code does today, by  
instanceof tests (never mind mutation revealing disparate identity).

The ES4 RI used the intrinsic namespace, and other namespaces, to  
access implementation helpers that underlay the prototype and any  
(mutable) static methods. Without namespaces, one could use private  
names of some kind (simply via lexical scope, I think), to access  
such helpers in an ES3-ish RI. With private names of some sort (the  
Name object idea) one could hide the helpers too.

I'm working to get the ES3+ RI restarted. It has as a goal avoiding  
too much magic in order to self-host the built-ins. "use lexical  
scope" and Object.defineProperty may be enough to self-host without  
being vulnerable to "user-code overrides".


>>> I have also assumed the existence of a "static" Function.apply which
>>> takes the function to be applied as an explicit first argument.
>>
>> This was part of ES4 and it's in JS1.7+ in Firefox.
>
> Good. I think it should be in ES3.1.

See my followup -- late night dream (or nightmare) on my part. JS1.7  
did add static generic Array.slice(arraylike, start, end) and so on  
(String.slice, etc.), but it did not add any such Function.apply/bind/ 
call. LSP is safe!

Could you suggest a new name for Function.apply (and the static bind  
and call, for that matter)? Thanks,

/be


More information about the Es-discuss mailing list