Reputation: 269
I am sorry for that the simple question first. But I just want to know what happen in the code below.
var indexobj = {
test : 1,
testFunction : function() {
document.getElementById('AA').innerHTML = indexobj.test++;
//this is i wanted
document.getElementById('BB').innerHTML = this.test++;
//NaN
setTimeout(indexobj.testFunction,1000);
},
}
setTimeout(indexobj.testFunction,1);
Here is the sample link below
http://jsfiddle.net/apss/JR5Xk/28/
Why in this example the ‘this’ inside the ‘testFunction’ function doesn’t mean ‘indexobj’ this object? Thanks for your help.
Upvotes: 4
Views: 226
Reputation: 193301
Because setTimeout
runs callback function in global object context, meaning that indexobj.testFunction
is invoked with this
being a window
object.
So you can either do
setTimeout(function() {
indexobj.testFunction();
},1000);
or using Function.prototype.bind
to create wrapper function with correct context:
setTimeout(indexobj.testFunction.bind(indexobj), 1000);
Another modern option from ES2015 is to use arrow function that preserves lexical context:
setTimeout(() => indexobj.testFunction(), 1000);
Upvotes: 6
Reputation: 147513
A function's this set set by:
How the function is called
the use of bind.
I doesn't matter where it's called from.
In this case, you have:
setTimeout(indexobj.testFunction,1000);
which passes the function referenced by indexobj.testFunction to be called later by setTimeout. When called, the function is called directly, so its this isn't set by the call and it defaults to the global object (window in a browser) or remains undefined in strict mode.
You can fix that in a number of ways, one is to pass a function that sets indexobj to this in the call:
setTimeout(function(){indexobj.testFunction()}, 1000);
or you can use bind as suggested by dfsq.
Arrow functions in the ES6 draft change how this is set, but that's for the next edition…
Upvotes: 3