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.)
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
frommultiply()
. The call stack says thatmultiply
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 forproductTimesFive
. That is real sad.Comment by johnjbarton — 07.09.10 @ 21:18
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 mungesthis
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 howarguments.callee
is specified.Comment by Jeff — 07.09.10 @ 21:35
ok: Bug 594258 – no jsdIStackFrame for ES5 bind()
Comment by johnjbarton — 07.09.10 @ 21:52
[…] 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
Double binding problem:
http://www.angrycoding.com/2011/09/to-bind-or-not-to-bind-that-is-in.html
Comment by Ruslan — 02.09.11 @ 12:49
[…] 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 Brendan Eich » Blog Archive » Harmony Of My Dreams — 19.08.14 @ 14:39