Function.prototype.bind (was: Topic list - pending changes and issues for the ES3.1 spec)

Garrett Smith dhtmlkitchen at gmail.com
Tue Sep 9 19:58:00 PDT 2008


On Tue, Sep 9, 2008 at 10:39 AM, Mark S. Miller <erights at google.com> wrote:
> On Tue, Sep 9, 2008 at 9:21 AM, Mark S. Miller <erights at google.com> wrote:
>> I still need to spec Function.prototype.bind in our funny spec language.
>>    Anyone care to contribute a draft?
>

> The simplest way to specify this would be in terms of the rest of the
> ES3.1 spec, i.e., a "self-hosting" spec. Perhaps like the following:
>

So self-hosting is where new features are written using EcmaScript
while the real implementation could be written in another language,
like C++?

This would be useful for testing. It would provide a common and
reliable reference, for example:-

if(!Function.prototype.bind) {
 Function.prototype.bind = function(context) {
 /** From EcmaScript H */
 ...
 };
}

In your example:-

>  Function.prototype.bind = function(self, var_args) {
>    var thisFunc = this;
>    var leftArgs = Array.slice(arguments, 1);
>    return function(var_args) {
>      var args = leftArgs.concat(Array.slice(arguments, 0));
>      return thisFunc.apply(self, args);
>    };
>  };
>

what are the two var_args parameter variables for? They are never used.

I prefer the variable name 'context' over 'self', to be more
consistent with the current spec, so:-

/**
 * @param {Object} context - the "this" value to be used.
 * @param {arguments} [1..n] optional arguments that are prepended
 * to returned function's call.
 * @return {Function} a function that applies the original
 * function with - context - as the thisArg.
 */
Function.prototype.bind = function(context) {
   var thisFunc = this,
         leftArgs = Array.slice(arguments, 1);
   return function() {
     var args = leftArgs.concat(Array.slice(arguments, 0));
     return thisFunc.apply(context, args);
   };
 };

But that would not be the most efficient way. This 'bind' method does
bind + partialApply. There are currently bind methods that do only
bind (and not partial apply)[JSAN]. It is simpler and more efficient,
when that's all you need.

However, if the requirement for bind is to perform bind +
partialApply, we could have our bind() return a function that does
either bind or bind + partialApply.

function GarrettsBind(context){
  var fn = this,
      slice = Array.prototype.slice,
      args,
      isPartial = arguments.length > 1;
      if(isPartial)
        args = slice.call(arguments, 1);

  // Strategy 1: just bind, not a partialApply
  if(!isPartial) {
    return function() {
      if(arguments.length !== 0) {
        return fn.apply(context, arguments);
      } else {
        return fn.call(context); // faster in Firefox.
      }
    };
  } else {
  // Strategy 2: partialApply
    return function() {
        return fn.apply(context,
         arguments.length===0 ? args:args.concat(slice.call(arguments));
    };
  }
}

Pure bind would keep things simple:

Function.prototype.bind = function(context) {
  return function() {
    if(arguments.length !== 0) {
        return fn.apply(context, arguments);
      } else {
        return fn.call(context); // faster in Firefox.
      }
  };
};

(Function.prototype.apply should be optimized when or arguments[1] is
undefined or its "length" is 0.)

[JSAN] http://openjsan.org/doc/r/rk/rkinyon/Function/bind/0.02/lib/Function/bind.html

> Post ES3.1, we hope to turn in general to the specification style that
> had been used for the ES4 spec -- SML + self-hosting. However, even
> the ES3 spec does make some use of self-hosting language such as "as
> if by the expression 'new Object()'", which the ES3.1 draft keeps, but
> clarifies to refer to the original binding of 'Object'. Could we use
> the same trick for Function.prototype.bind by saying something like
> "the original bindings of Array.slice, Array.prototype.concat, and
> Function.prototype.apply? Post ES3.1, to enable self-hosting specs,
> we'll need to solve this problem anyway. Any ideas how we should do
> that then?
>
Self-hosting new/complicated things sounds like a useful idea. It
clarify what the code does, make it testable, and provide useful code
for developers to fall back on (for implementations that don't yet
support the new feature).

Garrett
>
> --
>    Cheers,
>    --MarkM


More information about the Es-discuss mailing list