Now in SpiderMonkey and Firefox: ES5‘s Function.prototype.bind

This is just a brief note to point out that, as of the August 29th Firefox nightly (and I think as of the latest beta, but don’t quote me), SpiderMonkey (and Firefox) now implements ES5‘s new Function.prototype.bind method — native support for creating functions bound to a pre-specified this value:

var property = 42;
var obj =
    property: 17,
    method: function() { return this.property; }

var bound = obj.method.bind(obj);
assertEq(bound(), 17);

…or with pre-specified leading arguments:

function multiply()
  var product = 1;
  for (var i = 0, sz = arguments.length; i < sz; i++)
    product *= arguments[i];
  return product;

var productTimesFive = multiply.bind(null /* this */, 5);
assertEq(productTimesFive(4, 3, 2, 1), 120);

…and, in a feature present only in the ES5 bind implementation (and not in any of the numerous precursors), they even work with new:

function Vector()
  var args = arguments;
  this.length = arguments.length;
  this.get = function(i) { return args[i]; };
  this.set = function(i, v) { args[i] = v; };

var PartialVector = Vector.bind(null /* this, ignored with new */, 3, 7);

var threeSevenTen = new PartialVector(10); // new Vector(3, 7, 10)

For more information, see the article on Function.prototype.bind on MDC. For the utmost information, see the ES5 specification for the method.

As always, you can experiment with a version of Firefox with Function.prototype.bind by downloading a nightly from nightly.mozilla.org. (Don’t forget to use the profile manager if you want to keep the settings you use with your primary Firefox installation pristine.)


  1. Unfortunately the bind() call does not appear on the call stack in the debugger. This means a developer will not be able to know that an invisible hand operated on the arguments.

    Consider a break point on return product from multiply(). The call stack says that multiply was called from a source line that has arguments (4,3,2,1). Your loop just stepped 5 times and your product is 120 and you have no clue how that could possibly happen. The only way to debug is to visually parse the calling line and text search for productTimesFive. That is real sad.

    Comment by johnjbarton — 07.09.10 @ 21:18

  2. I’m not so sure that’s the case. Internally we push another frame inside the bound function in order to invoke the target function with the right this and arguments. That should be able to be exposed somehow during debugging — no reason a debugger can’t see that the bound-function frame munges this and perhaps inserts these arguments. File a bug and CC me (and the usual debugging suspects), and I’m sure we can work out some sort of way to expose the boundness of the function here. (However, very shortly I’ll be going on vacation for a couple weeks, so I probably will be unable to work on the patch or review the fix, unless either is delayed beyond my return.)

    As for the bound function not showing up via arguments.callee or such, however, this is deliberate and is required by the ES5 specification. See the definition of [[Call]] for bound functions and compare that to how arguments.callee is specified.

    Comment by Jeff — 07.09.10 @ 21:35

  3. ok: Bug 594258 – no jsdIStackFrame for ES5 bind()

    Comment by johnjbarton — 07.09.10 @ 21:52

  4. [...] Correspondence Principle casualty: this default binding. When you call o.m() in JS, unless m is a bound method, this must bind to o. But for all functions in ES5 strict mode, and therefore in Harmony (based on [...]

    Pingback by Harmony Of My Dreams | Brendan Eich — 18.01.11 @ 17:05

  5. Double binding problem:

    Comment by Ruslan — 02.09.11 @ 12:49

RSS feed for comments on this post. TrackBack URI

Leave a comment

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>