Today I found out a rather strange behaviour that happens when you pass the method of an object as a function in Javascript.
setTimeout(myObject.test, 100); // "this" is the global object window
The method "test" is correctly invoked, but "this" is not the object "myObject" but instead the global object "window". I can get the expected behaviour when I do something like this:
setTimeout(function(){myObject.test()}, 100); // "this" is myObject
This seems to me rather strange. Can anybody explain, why this is.
-
1What you are describing can be strange, when you are used to languages like AS3 or Java - but in JS this is the expected behaviour, the default-scope is "window" for any event or timeout-function ect. so you usually always have to go through anonymous functions.Olaf Horstmann– Olaf Horstmann2013年03月25日 09:25:28 +00:00Commented Mar 25, 2013 at 9:25
2 Answers 2
Consider this pseudo-representation how JavaScript will interpret setTimeout(myObject.test, 100);
function setTimeout(func, millisec) {
//some code...
func(); //"this" in func will point to window
//some code...
}
But when you do this - setTimeout(function(){myObject.test()}, 100);, setTimeout will execute the anonymous function you passed, so this the anonymous function will still point to window, but that anonymous function calls another function myObject.test(), since, function is being called as a method of an object, this will point to that object.
You can solve this by using a cool JS function bind.
setTimeout(myObject.test.bind(myObject), 100); //now "this" will point to myObject.
Comments
The run time will execute the function argument (1st argument) for setTimeout on window object, and you put the test method directly as the argument, so you see this is bond to window object in your first case.
In your second case, the function executed on window object is your anonymous function function() { myObject.test() }, however, the test method is invoked on myObject, that's why you see this is bond to myObject