问题
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
...
回答1:
When you pass a.i
to PubSub.subscribe
, you've "detached" the i
function from a
, its invocation context. Either use an anonymous function to maintain the binding:
PubSub.subscribe("test", function (x) { a.i(x); });
or use Function.bind to preserve a
as this
whenever i
is called:
PubSub.subscribe("test", a.i.bind(a));
N.B. Function.bind
is not supported in all browsers, so you'll want to use the shim.
来源:https://stackoverflow.com/questions/10107340/javascript-pub-sub-implementation-works-for-functions-but-not-objects-methods