Why does `this` change when passing the function argument as string or reference?
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...
Example 1
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.
Example 2
eval()
is meant to adopt its execution context of where it is called, in this case, window
. It also produces the expected result.
Example 3
When passing a string to setTimeout()
, I'd imagine it is ran through something very similar to eval()
. It too produces the expected result.
Example 4
this
becomes Window
in this example. This is what I am interested in.
Example 5
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 itsthis
always beWindow
when called with()
?Is the only way to keep its
this
asa
to pass it as a string tosetTimeout()
/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);
精彩评论