Have a look at this:
var a = {
b: function() {
console.log(this);
}
}
// Example 1
a.b(); // a
// Example 2
eval('a.b()'); // a
// Example 3
setTimeout('a.b()', 100); // a
// Example 4
setTimeout(a.b, 100); // Window
// Example 5
var c = a.b;
c(); // Window
jsFiddle.
Assuming the expected result is what I expected...
When calling b()
, the property of an Object
, this
becomes the property's Object
, here it's the parent a
. It produces the expected result.
eval()
is meant to adopt its execution context of where it is called, in this case, window
. It also produces the expected result.
When passing a string to setTimeout()
, I'd imagine it is ran through something very similar to eval()
. It too produces the expected result.
this
becomes Window
in this example. This is what I am interested in.
Here the this
becomes Window
, because c
's parent object is Window
.
When passing only a reference to a function (e.g. a.b
), will its this
always be Window
when called with ()
?
Is the only way to keep its this
as a
to pass it as a string to setTimeout()
/ setInterval()
?
When passing only a reference to a function (e.g. a.b), will its this always be Window when called with ()?
Yes
Is the only way to keep its this as a to pass it as a string to setTimeout() / setInterval()?
No. Create a new function instead.
setTimeout(function() { a.b() }, 100);
Developers are often confused about javascript's this keyword. The most important thing to remember is that it is provided by the call.
In the 4th example:
// Example 4 setTimeout(a.b, 100); // Window
the first argument is a reference to the function, so it's called without any "parent" object. Since the call doesn't provide an object, this is set to window
.
Your comment on example 5:
Here the this becomes Window, because c's parent object is Window.
is not really incorrect. Because the function call doesn't provide an object to use as this
, it is set to window
(which is the default when no object is provided).
Is the only way to keep its this as a to pass it as a string to setTimeout() / setInterval()?
No. Other than calling it as a property of an object, you can use call
or apply
:
var x = a.b;
x.call(a);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With