Javascript pub/sub implementation works for functions, but not objects' methods

北城余情 提交于 2019-12-06 14:33:51

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!