I have a class that is structured something like this
function myClass () {
this.varA = 0;
}
myClass.prototype.consts = {
someConst : 1,
anotherConst : 1000,
}
myClass.prototype.startIt = function () {
window.setTimeout(this.brokenFunc.bind(this), this.consts.anotherConst);
}
myClass.prototype.brokenFunc = function () {
this.varA += this.consts.someConst;
window.setTimeout(this.brokenFunc.bind(this), this.consts.anotherConst);
}
// Example call
var myObj = new myClass();
myObj.startIt();
This works fine on most Android devices — but a user running Android 2.3 has now informed me that it doesn’t work and I could reproduce the error in an emulator. First, it says TypeError: Result of expression 'this.brokenFunc.bind' [undefined] is not a function for this line (within startIt):
window.setTimeout(this.brokenFunc.bind(this), this.consts.anotherConst);
Fair enough, I thought, and did the old var _this = this trick to get around the bind call. But now it says TypeError: Result of expression 'this.consts' [undefined] is not an object in this line
this.varA += this.consts.someConst;
And I’m a little lost. How can this piece of code not work? Especially since it works in most Android versions.
By default,
setTimeoutinvokes functions withthisof the global object (i.e.,window, in the browser). (Side note: in strict mode, it’sundefinedinstead.) Thus, when you don’t usebind, thethisbrokenFuncis nowwindowinstead of the object that registered the timeout.In order to preserve the
thisfromstartIt, you’ll need to wrap your call in an anonymous function:Your first error happened because the Android 2.3 browser doesn’t support the EMCAScript 5
bindfunction. Your second error appeared becausethis.constsis reallywindow.consts, which doesn’t exist. Just wrap the call in an anonymous function that hasthatin its scope, and call the function fromthat.