I have code like this:
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;
}
}
When running ws2812.speech("");
inside console, everything works. However, when paired with the Annyang
library, I get this:
Uncaught TypeError: this.set is not a function
ws2812.speech @ script.js:29
b.annyang.init.d.onresult @ annyang.min.js:6
What's wrong?
[edit]
The command is added like this:
annyang.addCommands({"ustaw *term światło":ws2812.speech});
Specifically, inside annyang, this line fails:
f[h].callback.apply(this,m)
Is replacing this
with ws2812
the only way to work around this?
ws2812.speec is defined as a static function. So this
keyword inside it refers to itself (function scope), not the object ws2812 you want.
To fix it, either of these quick choices can be made:
Choice#1 > Call the static function ws2812.set properly
So your code becomes:
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;
}
}
However, there are some possibilities that this
keywords referenced in other parts in the rest of the code may also suffer from this issue. You may need to go check it.
Choice#2 > Convert to prototype functions
This way you can retain this
keywords, but the functions are no longer static. You need to instantiate an instance object of ws2812
to use.
So your declarations becomes:
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;
}
}
Then use it via instance of object instead:
var myWs2812 = new ws2812();
myWs2812.speech('hello world!'); // inside it, should call this.set properly
Choice#3 > Bind 'this' object when calling
In case you insist you don't want to modify the implementation of this ws2812
. It's okay to leave it and bind this object when using it instead.
So when you call ws2812.speech
, you need to use function.prototype.call
and pass in ws2812.set
as this.
ws2812.call( ws2812.set, 'hello world!' );
However, this doesn't look much semantic and it may cause confusions in the future use for people who will maintain this code.
I'll leave it for you to decide which would be the best way for you to go.