tags:

views:

50

answers:

1

Consider the following example:

var funcToCall = function() {...}.bind(importantScope);

// some time later
var argsToUse = [...];
funcToCall.apply(someScope, argsToUse);

I want to preserve 'importantScope' of funcToCall. Yet, I need to use apply to apply an unknown number of arguments. 'apply' requires that I provide 'someScope'. I don't want to change the scope, I just want to apply the arguments to the function and preserve its scope. How would I do that?

+4  A: 

You can pass any old object (including null) as the first argument to the apply() call and this will still be importantScope.

function f() {
    alert(this.foo);
}

var g = f.bind( { foo: "bar"} );

g(); // Alerts "bar"
g.apply(null, []); // Alerts "bar"

The bind method creates a new function in which the this value is guaranteed to be the object you passed in as the parameter to the bind call. Regardless of how this new function is called, this will always be the same. A simple implementation would look like this (note the implementation specified ECMAScript 5 and that in Prototype does more than this but this should give you the idea):

Function.prototype.bind = function(thisValue) {
    var f = this;
    return function() {
        return f.apply(thisValue, arguments);
    };
};
Tim Down
@Nick: so, just pass `null`.
Matt Ball
What do you mean by "any old object" if I pass an object to apply, that object will become the scope. Wouldn't it? By the time the call is being made I no longer have access to "importantScope"
Nick
@Bears Passing null binds the global object as the scope. I want to "preserve" the scope, whatever it was.
Nick
A function created by `bind` will have the `this` value you bound to it, no matter how it's called. It might help to see an implementation of `Function.prototype.bind`. I'll add one to my answer.
Tim Down
Indeed it does, now I'm confused on why that is. Can you shed some light? {} is supposed to be made 'this' inside g. {} doesn't have a property foo, yet this works. Why is that? Wouldn't that mean that the docs here are not accurate: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply
Nick
The implementation of bind answers the question for me. Thank you.
Nick
The original function and the function returned by calling its `bind` method are different objects. The "bound" function can be seen as a wrapper that calls the original function with the `this` value specified in the bind call while making no use at all of its own value of this.
Tim Down
Note this lightweight implementation of `Function#bind` doesn't have partial application, so it's not ECMAScript Fifth Edition compliant. Prototype's implementation [eg](http://stackoverflow.com/questions/2128251#2128296) is complete.
bobince
Good point. The plan was just to illustrate the general idea of `bind` but I should have made that clear. I'll update my answer.
Tim Down