views:

39

answers:

3

I have a makeshift events system in JS and the attacher looks like this:

events.attach(events.NEW_TASK,this.update);

Where this.update is a callback/handler/function. The problem is, when the dispatcher tries to call this handler, it loses it's original context. How can I bind the handler with the context of the object that calls the attach function without passing this as an argument and using that?

Edit: I should also mention that it will be somewhat of a framework so it has to be simple for other developers so preferably not needing to store the context in another variable.

A: 

You could store the reference of "this" in a local variable and try calling the function using it

var that = this;

events.attach( events.NEW_TASK, function( ) { that.update(); } );
Kunal
+2  A: 

Another option, using the Function.prototype.bind method, part of the new ECMAScript Standard:

events.attach(events.NEW_TASK, this.update.bind(this));
CMS
... which is all very well but not usable as a general solution. Yet.
Tim Down
@Tim, an *almost* standard compliant implementation is really simple to write (~8 lines in the answer I link), and we will have native implementations soon in major JS engines ( [WebKit](https://bugs.webkit.org/show_bug.cgi?id=26382), [Mozilla](https://bugzilla.mozilla.org/show_bug.cgi?id=429507), [V8](http://code.google.com/p/v8/issues/detail?id=384)). I'm sure that this will be the most used method in the near years to come, there is no reason to not use the *standard* way...
CMS
Well, I pretty much agree with you. My answer avoids extending `Function.prototype` because I prefer not to extend native prototypes and because I prefer not to have two separate branches for different browsers where possible.
Tim Down
@Tim, yes, I'm also against to extending native prototypes with *non-standard* methods, IMHO in this case (and for example the ES5 `Array.prototype` additions also) I see no problem extending it for compatibility, because I know that native implementations will come *soon or later*. The difference between the branches will be that in browsers with native implementations, the methods will be *ultra-fast*, compared to what you can achieve with a custom implementation...
CMS
Yes, I appreciate the benefits you mention. To be honest, I'm not dogmatically opposed to extending `Function.prototype` and `Array.prototype`. I'm just wary of other scripts in the page that might have had the same idea and done it wrong.
Tim Down
+1  A: 

Until ECMAScript 5 has wide adoption in browsers, you could use your own implementation of Function.prototype.bind:

function bind(func, thisObj) {
    return function() {
        func.apply(thisObj, arguments);
    };
}

events.attach(events.NEW_TASK, bind(this.update, this));
Tim Down