I’m trying to implement a simple Pub/Sub object in javascript, and here’s my code:
var PubSub=new function(){
this.subscriptions=[];
this.subscribe=function(topic,callback){
if(!this.subscriptions[topic]){
this.subscriptions[topic]=[];
}
this.subscriptions[topic].push(callback);
}
this.unsubscribe=function(topic,callback){
if(this.subscriptions[topic]){
for(var i=this.subscriptions[topic].length-1;i>=0;i--){
if(this.subscriptions[topic][i]==callback){
this.subscriptions[topic].splice(i,1);
}
}
}
}
this.publish=function(topic,data){
if(this.subscriptions[topic]){
for(var i=this.subscriptions[topic].length-1;i>=0;i--){
this.subscriptions[topic][i](data);
}
}
}
}
Now, subscribing a simple function, and then publishing some stuff works great:
PubSub.subscribe("test",print); //print: shell function
PubSub.publish("test","hello"); //print outputs "hello"
But, subscribing a function, which is an object’s method doen’t work:
var a=new function(){
this.c=0;
this.i=function(x){
this.c+=x;
}
}
PubSub.subscribe("test",a.i);
PubSub.publish("test",17);
a.c; //is still 0
I also tried using apply (assuming data is an array):
PubSub.publish=function(topic,data){
...
this.subscriptions[topic][i].apply(this,data);
...
}
It doesn’t work either, though I believe it’s not the same problem: I think the this object passed by apply overrides the this object of a, and therefore a.i tries to set PubSub.a instead of a.a…
When you pass
a.itoPubSub.subscribe, you’ve “detached” theifunction froma, its invocation context. Either use an anonymous function to maintain the binding:or use
Function.bindto preserveaasthiswheneveriis called:N.B.
Function.bindis not supported in all browsers, so you’ll want to use the shim.