2

次のようなコードがあります。

var ws2812 = {};


ws2812.set = function(r,g,b){
    $.get( "/light?r="+r+"&g="+g+"&b="+b, function( data ) {
        console.log("Light set to:"+"/light?r="+r+"&g="+g+"&b="+b);
    })
};

ws2812.speech = function(word){
    switch(word){
        case "czerwone":
            this.set(255,0,0);
        break;
        case "zielone":
            this.set(0,255,0);
            break;
        case "niebieskie":
            this.set(0,0,255);
            break;
        case "białe":
            this.set(255,255,255);
            break;
        default:
            this.set(0,0,0);
            break;

    }
}

ws2812.speech("");コンソール内で実行すると、すべてが機能します。ただし、Annyangライブラリと組み合わせると、次のようになります。

Uncaught TypeError: this.set is not a function 
ws2812.speech @ script.js:29  
b.annyang.init.d.onresult @ annyang.min.js:6

どうしたの?

[編集]

コマンドは次のように追加されます。

annyang.addCommands({"ustaw *term światło":ws2812.speech});

具体的には、annyang 内で、次の行が失敗します。

f[h].callback.apply(this,m)

これを回避する唯一の方法でthis置き換えることはできますか?ws2812

4

1 に答える 1

2

ws2812.speec は静的関数として定義されています。したがって、その中のキーワードは、必要なオブジェクトws2812thisではなく、それ自体 (関数スコープ) を参照します。

これを修正するには、次のいずれかの簡単な選択を行うことができます。


選択肢 #1 > 静的関数 ws2812.set を適切に呼び出す

したがって、コードは次のようになります。

ws2812.speech = function(word){
    switch(word){
    case "czerwone":
        ws2812.set(255,0,0);
    break;
    case "zielone":
        ws2812.set(0,255,0);
        break;
    case "niebieskie":
        ws2812.set(0,0,255);
        break;
    case "białe":
        ws2812.set(255,255,255);
        break;
    default:
        ws2812.set(0,0,0);
        break;

    }
}

ただし、thisコードの残りの部分で参照されているキーワードもこの問題に悩まされる可能性があります。確認しに行く必要があるかもしれません。


選択肢 2 > プロトタイプ関数に変換する

このようにしてthis、キーワードを保持できますが、関数は静的ではなくなります。使用するインスタンス オブジェクトをインスタンス化する必要がありますws2812

したがって、宣言は次のようになります。

var ws2812 = function(){};


ws2812.prototype.set = function(r,g,b){
    $.get( "/light?r="+r+"&g="+g+"&b="+b, function( data ) {
        console.log("Light set to:"+"/light?r="+r+"&g="+g+"&b="+b);
    })
};

ws2812.prototype.speech = function(word){
    switch(word){
    case "czerwone":
        this.set(255,0,0);
    break;
    case "zielone":
        this.set(0,255,0);
        break;
    case "niebieskie":
        this.set(0,0,255);
        break;
    case "białe":
        this.set(255,255,255);
        break;
    default:
        this.set(0,0,0);
        break;

    }
}

次に、代わりにオブジェクトのインスタンスを介して使用します。

var myWs2812 = new ws2812();
myWs2812.speech('hello world!'); // inside it, should call this.set properly

選択肢 #3 > 呼び出し時に「this」オブジェクトをバインドする

this の実装を変更したくないと主張する場合ws2812代わりに使用する場合は、そのままにしてこのオブジェクトをバインドしても問題ありません。

したがって、 を呼び出すときは、このように使用して渡すws2812.speech必要があります。function.prototype.callws2812.set

ws2812.call( ws2812.set, 'hello world!' );

しかし、これはあまりセマンティックに見えず、このコードを保守する人が将来使用する際に混乱を招く可能性があります。


どちらがあなたにとって最善の方法であるかは、あなたの判断にお任せします。

于 2015-06-14T17:07:34.237 に答える