【问题标题】:this.set is not a functionthis.set 不是函数
【发布时间】:2015-08-30 04:10:07
【问题描述】:

我有这样的代码:

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 是解决此问题的唯一方法吗?

【问题讨论】:

  • 您是否将未绑定的speech 函数作为回调传递?请在您的示例中包含失败的代码。

标签: javascript annyang


【解决方案1】:

ws2812.speec 被定义为静态函数。所以它里面的this关键字是指它自己(函数作用域),而不是你想要的对象ws2812

要修复它,可以选择以下任一快速选择:


选择#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

Choice#3 > 调用时绑定'this'对象

如果您坚持不想修改此ws2812 的实现。留下它并在使用它时绑定这个对象是可以的。

所以当你调用ws2812.speech时,你需要使用function.prototype.call并传入ws2812.set这样。

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

但是,这看起来没有太多语义,并且可能会在将来维护此代码的人的使用中引起混淆。


我会留给您决定哪种方式最适合您。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 2018-06-13
    • 1970-01-01
    • 2017-05-06
    • 2019-12-20
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多