1

単純なPub/Subオブジェクトをjavascriptで実装しようとしていますが、コードは次のとおりです。

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);
            }
        }
    }
}

さて、単純な関数をサブスクライブしてから、いくつかのものを公開すると、うまく機能します。

PubSub.subscribe("test",print); //print: shell function
PubSub.publish("test","hello"); //print outputs "hello"

ただし、オブジェクトのメソッドである関数をサブスクライブしても機能しません。

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

また、applyを使用してみました(データが配列であると想定):

PubSub.publish=function(topic,data){
    ...
        this.subscriptions[topic][i].apply(this,data);
    ...
}

同じ問題ではないと思いますが、どちらも機能しませんthis。applyによって渡されたthisオブジェクトは、のオブジェクトをオーバーライドすると思いますa。したがって、 ...の代わりにa.i設定しようとします。PubSub.aa.a

4

1 に答える 1

2

に渡すa.iと、その呼び出しコンテキストから関数PubSub.subscribeが「切り離され」ます。バインディングを維持するには、匿名関数を使用してください。ia

PubSub.subscribe("test", function (x) { a.i(x); });

または、いつでも呼び出されるようFunction.bindに保存するために使用します。athisi

PubSub.subscribe("test", a.i.bind(a));

NBはすべてのブラウザでサポートされているわけではないため、shimFunction.bindを使用することをお勧めします。

于 2012-04-11T13:55:10.570 に答える