Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting context from an object inside a callback in Javascript

I have a case where I have an object, "foo", that needs to call a callback on another object, "bar", and I need the context within the callback to be that of "bar". The kicker though, is that beyond getting its callback from "bar", "foo" should not know anyting about it.

Example:

var foo = 
{
    message: "Hello foo",
    doStuff: undefined
};

var bar =
{
    message: "Hello bar",
    callback = function ()
    {
        alert(this.message);
    }

};

foo.doStuff = bar.callback;

foo.doStuff();

I realize that normally you would use "call" or "apply" to switch the context to bar but in my particular case, at the time of calling foo.doStuff() I no longer have information about where the callback came from. So is there another way of figuring the context (say from within the callback function itself)?

like image 453
user1601333 Avatar asked Aug 13 '26 02:08

user1601333


2 Answers

So is there another way of figuring the context (say from within the callback function itself)?

Nope. Not without some extra specific before you pass the callback. If all you have is a function reference, you typically have no context. But with some prep, there are some solutions.

You could wrap the callback. When this is invoked, bar.callback() will be called in it's full form, preserving the context of bar.

foo.doStuff = function() { bar.callback(); };

Or in modern JS engines you can bind the callback to a specific context.

foo.doStuff = bar.callback.bind(bar);

Or use underscore.js to do that in all JS engines.

foo.doStuff = _(bar.callback).bind(bar);

Or make your own bind function if you want compatibility with old engines and dont want to use a whole library for it.

var bind = function(fn, context) {
  return function() {
    fn.call(context);
  };
};
foo.doStuff = bind(bar.callback, bar);

All that said, a simple wrapper is usually the simplest and most common. It's got few drawbacks, it's fast, easy to understand, and gives you lots of control over what gets invoked with what arguments. In this case, this form makes the most sense I think.

foo.doStuff = function() { bar.callback(); };
like image 189
Alex Wayne Avatar answered Aug 14 '26 16:08

Alex Wayne


Use closure for bar.

var foo = {
    message: "Hello foo",
    doStuff: undefined
};

var bar = (function() {
    var message = "Hello bar";
    return {
        callback: function() {                
            alert(message);
        }
    };
})();


foo.doStuff = bar.callback;
foo.doStuff();
​

jsfiddle

like image 31
glkz Avatar answered Aug 14 '26 15:08

glkz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!