associates an object to use as this (aka the receiver) when the function is invoked

associates additional parameters to be passed to the function when the function is invoked (aka currying).

bind() does this by returning a new function, which when invoked, arranges for the object you want as the receiver and the additional parameters to be passed to the original function. It hides these values in the newly created function, associated with the closure the function was returned from.

bind() is frequently used for callbacks and event handlers, which typically allow you to pass a function as the callback, but don't provide a way to specify the receiver or additional parameters for the actual call to the callback.

The bug concerns providing a better debug story around functions that have been bind()'d. Because the current story isn't very pretty. When you stumble upon a bind()'d function in the debugger, you see the source for the bind() function itself, which isn't what you want to see. In addition the resulting bound function is usually anonymous, which means your stack traces, profile reports, etc, will be filled with (anonymous function) entries.

garbage

Calling bind() creates a new function object every time it's called. Not just a string, or empty object, or array. A function. Which I'm guessing is more expensive than simpler objects. [yes, I should do some measurements.] A closure is also created and associated with the function (which is where the receiver and curried arguments are stored). More garbage.

Now imagine that, for whatever reason, you need to add and then remove
a callback frequently, over and over again, for some reason. Or set a timer over and over again. And you're using bind(). Think of the garbage you're creating.

So why does this [using bind()] suck? Two reasons: it's long-ish to type, and it doesn't do what the dot operator does -- i.e., return the same function object every time.

It is longer, and therefore yuckier. It's also often not DRY (obj referenced twice):

setTimeout( obj.method.bind(obj, "John"), 100 );

The second point is explained by Alex in his post:

Many functions, both in the DOM and in the library, accept functions
as arguments. ES5 provides a bind() method that can ease the use of
these functions when the passed method comes from an object. This is,
however, inconvenient. E.g.:

node.addEventListener("click", obj.method.bind(obj, ...));

Also, insufficient. Event listeners can't be detached when using
Function.prototype.bind:

// doesn't do what it looks like it should
node.removeEventListener("click", obj.method.bind(obj, ...));

So the trick here, if you want to use removeEventListener(), is that you have to store the result of a single call to bind() and then use that value in subsequent addEventListener() / removeEventListener() paired calls. Alex's post suggests a new language feature to work around this (btw, I'm not in favor of his proposed language feature).

why are we in a bind with bind() today?

It's pretty obvious to see how we got to the point where you need to use bind() in your code today.

Historically, JavaScript was a glue language that let you do a light amount of programmatic processing against stuff in your page. When specifying a callback/listener, you didn't have to worry so much about the receiver of the function you passed in; you were probably using global variables instead of creating your own little objects.

And so the places that take callbacks, like setTimeout(),
onload handlers, etc, didn't really have a need for you to specify the receiver of of the callback when it was invoked. The receiver was always ... well, whatever it was for your callback.

Fast-forward a decade, and now we have people building huge systems out of JavaScript, using some sort of "class" story, or living the hippy prototype lifestyle, or who knows what kids are doing today. In any case, there's often an "object" in the picture, and you'd often like to arrange to have that object be the receiver of the callback. Quite often, you'd like for the callback function to be a method of an object, and have the receiver of the callback be that object.

The problem is, there's no where to put the receiver; all the pre-existing callback patterns just allowed the use of a function parameter. The trick with bind() is that it attaches the receiver, and possibly curry'd arguments, to an invisible bag wrapped around a newly created function which is a delegated version of your callback function. Nature will find a way.

how can we fix the evils of bind()?

For me, the root of the problem is that we're passing the method receiver in a secondary channel, the bound function. So, stop doing that. Pass it explicitly.

In terms of being able to handle the removeEventListener() case as well, when using the ECMAScript 5 version of bind() you would have to arrange to store a copy of the bound function, so you can send the exact same function both addEventListener() and removeEventListener(). My proposed versions could do a compare against the parameters or array elements, allowing you to use the exact same parameters on addEventListener() and removeEventListener().

This invocation pattern works the same for the other form of call that I proposed.

Curried arguments can be handled the same way the receiver parameter is handled; passed as additional arguments to addEventListener() (not needed for removeEventListener()?), or an additional element in the array where the listener argument was previously used. One simplification would be to allow a single curried argument - other callback systems typically refer to this as userData or clientData - rather than deal with a variadic list. It's simple enough to combine multiple curried arguments into an object or array for use as a userData argument.

actually, bind() isn't always evil

Although I've spent this entire post complaining about bind(), I will acknowledge it's power and usefulness. Particularly in meta-programming and function programming.

My primary complaint is having to use bind() is something pedestrian as callbacks. That's too much.

1) Saying that `bind` gets in a way of debugging is similar to saying that anonymous functions get in a way of debugging. This is a valid argument of course, but it's something debuggers/profilers can relatively easy take care of. As you might know, `Function.prototype.toString` is specified to return implementation-dependent representation of a function (in both ES3 and ES5); Nothing is stopping implementations from returning source of original function prepended with something like [Bound function] and maybe also [Target function: ...], [Bound arguments: ...], etc.

2) I don't understand the "garbage" argument. I'm not sure why you think that closure is formed on creation of bound function. There is no change in scope of the function that gets bound to an object (and/or arguments). ES5 even explicitly states that bound function — contrary to regular native function objects — doesn't have [[Scope]] (internal property which is a reference to a lexical environment in ES5 and scope chain (list of activation objects) in ES3). In ES5 `bind` merely creates a wrapper object (that's made to look almost like a function object). This wrapper delegates invocation (`()` operator, internal [[Call]] method), instantiation (`new` operator, internal [[Construct]] method) and property existence check (`in` operator, internal [[HasInstance]] method) to an original (target) function. No change of [[Scope]] of target function is ever made and no [[Scope]] is ever created on a bound function.

Now compare this to a popular replacement of `bind` — creating a wrapping function:

In a second example, wrapping function DOES in fact have a scope and a closure DOES get formed. Now, speaking of garbage, imagine if this second snippet was buried somewhere deep inside bunch of other code and how much garbage handler function would close over (pretty common case, imo):

(function(){

// ... some code and variables (function(){

// ... some more code and variables el.addEventListener('click', function(){

// all the variables from the enclosing scope // are now closed over in this function

obj.method(); }, false);

})();})();

When compared to wrapping-function bind replacement, I would think that `bind` makes for a more performant code, not the other way around.

3) Longish to type argument is a bit weak, in my opinion.

This is how we used to do things:

el.addEventListener('click', function(){ obj.method() }, false);

And this is how we can do it with bind now:

el.addEventListener('click', obj.method.bind(obj), false);

`bind` one is shorter. And it avoids creation of closure too. It's a win/win :)

Of course, `el.addEventListener('click', obj, 'method', false)` would be even shorter, but then you end up with 4 arguments and that's already something begging for "too many arguments" type of refactoring :)

4) The point about `bind` retuning new function every time — and that being "bad thing" — is interesting. I can see how it's inconvenient in case of `addEventListener`/`removeEventListener` (although in context of browser scripting, it's recommended to avoid frequent removal of listeners in favor of delegation).

1) bind being "anonymous"; see the previously mentioned bug report by NV, which modify's the toString() method of the bound function for Web Inspector's internal code (doesn't help anyone but Web Inspector developers). For debug purposes, it might be nice if there was a "standard" for the toString(), or even better, or if there were a way to introspect over these bound functions.

2) You caught me, I hadn't fully read and/or understood the spec. Not sure I understand all the ramifications of it yet. But you're right, no new scope is created by just creating the bound function. Even in the case of libraries (jQuery, Dojo, etc) implementations of bind(), the scope is going to be container to that of the bind() implementation, which shouldn't be leaky, but it's something.

I finally caught up on JavaScriptCore's Bug 26382: [ES5] Implement Function.prototype.bind, and there's some interesting bits in there about the eventual implementation, for folks interested in this stuff. Most interesting was realizing the shortcuts they planned on making, which didn't seem to safe to me at the time, but makes more sense now.

I happen to be watching the bind() implementation.

3) 'longish' isn't a terribly strong argument, blame Alex for that one :-) DRY is nice though, as in not having to repeat obj twice in the "obj.method.bind(obj)". This would be somewhat offset if the common case for "obj" is "this", leaving us with "this.method.bind(this)" is at least something that you can cut+paste around safely, assuming that's the style you're using for your code.

4) w/r/t this is at least one type of garbage I was referring to - the newly returned function itself.

1) It's not just about `toString`. Look at http://elv1s.ru/files/js/bind_vs_closure.png and http://elv1s.ru/files/js/bind_vs_closure.html

The bound function is pointing to the Function.prototype.bind, which isn't very helpful. For me, that's the main problem of prototype.js-like bind. I'm pretty sure native `bind` won't have this problem.

> The bound function is pointing to the Function.prototype.bind, which isn't very helpful. For me, that's the main problem of prototype.js-like bind. I'm pretty sure native `bind` won't have this problem.

Define "pointing to". All property accesses on the bound function delegate to the original function? I don't think that's what the spec says (my current understanding), and I'm not sure that's the right thing to do anyway.

I think I'd rather that bound functions have some new special property that points to the original function. In the spec, it's the [[TargetFunction]] internal property, but internal properties aren't "real".

I meant the link in Web Inspector ("bind_vs_closure.html:10" in my example) is pointing to the line number where the bound function was created.

> I think I'd rather that bound functions have some new special property that points to the original function. In the spec, it's the [[TargetFunction]] internal property, but internal properties aren't "real".

I suppose [[TargetFunction]] might be accessed within Web Inspector's back-end. I hope so.