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);
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
acelot
  • 752
  • 2
  • 7
  • 26
  • 1
    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? – Quintin Robinson Nov 08 '12 at 01:52
  • You are passing the parameter, you're just not using it. And I don't understand why. – bfavaretto Nov 08 '12 at 02:10
  • 2
    @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. – I Hate Lazy Nov 08 '12 at 02:17

2 Answers2

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)

EleventyOne
  • 7,300
  • 10
  • 35
  • 40
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);
I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77