How to pass context to anonymous function?
Asked Answered
M

2

29

There are some function, thats do something long work and its provides callback.

someFunc: function(argument, callback, context) {
  // do something long

  // call callback function
  callback(context);
}

In application I use this function

someFunc('bla-bla', function (context) {
  // do something with this scope
  context.anotherFunc();
}, this);

How to implement callback function without passing context parameter?

Need some like this:

someFunc('bla-bla', function () {
  // do something with this scope
  this.anotherFunc();
}, this);
Moat answered 8/11, 2012 at 1:49 Comment(3)
So in your final example it appears you are passing the context (to something at least) are you just curious on how to reference the argument if it isn't named?Lipread
You are passing the parameter, you're just not using it. And I don't understand why.Peculium
@bfavaretto: OP is using it by passing it into the callback so that the callback can take advantage of the methods of the outer this value. So the question is how to achieve the last code block... getting the proper this in the callback so it doesn't need to be passed as an argument.Indefectible
H
43

The accepted answer seems somewhat outdated. Assuming you're operating on a relatively modern browser, you can use Function.prototype.bind in vanilla javascript. Alternatively, if you are using underscore or jQuery, you can use _.bind or $.proxy respectively (which will fallback to call/apply if necessary).

Here is a simple demonstration of these three options:

// simple function that takes another function
// as its parameter and then executes it.
function execute_param(func) {
    func();
}

// dummy object. providing an alternative context.
obj = {};
obj.data = 10;

// no context provided
// outputs 'Window'
execute_param(function(){
    console.log(this);
});

// context provided by js - Function.prototype.bind
// src: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
// outputs 'Object { data=10 }''
execute_param(function(){
    console.log(this);
}.bind(obj));

// context provided by underscore - _.bind
// src: http://underscorejs.org/#bind
// outputs 'Object { data=10 }'
execute_param(_.bind(function(){
    console.log(this);
},obj));

// context provided by jQuery - $.proxy
// src: http://api.jquery.com/jQuery.proxy/
// outputs 'Object { data=10 }'
execute_param($.proxy(function(){
    console.log(this);
},obj));

You can find the code in a jsfiddle here: http://jsfiddle.net/yMm6t/1/ (note: ensure that the developer console is open, or you won't see any output)

Hunterhunting answered 20/10, 2013 at 1:26 Comment(3)
Yes. Now I'm using underscore everywhere :)Moat
@PiONeeR Yeah, me too :) You might want to reconsider what should be the accepted answer.Hunterhunting
How do you bind this under another variable name? Like .bind(that)?Grillwork
I
15

Use Function.prototype.call to invoke a function and manually set the this value of that function.

someFunc: function(argument, callback, context) {
    callback.call(context); // call the callback and manually set the 'this'
}

Now your callback has the expected this value.

someFunc('bla-bla', function () {
  // now 'this' is what you'd expect
    this.anotherFunc();
}, this);

Of course you can pass arguments like normal in the .call invocation.

callback.call(context, argument);
Indefectible answered 8/11, 2012 at 1:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.