Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `this` change when passing the function argument as string or reference?

Tags:

javascript

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.

  1. When passing only a reference to a function (e.g. a.b), will its this always be Window when called with ()?

  2. Is the only way to keep its this as a to pass it as a string to setTimeout() / setInterval()?

like image 753
alex Avatar asked May 04 '11 12:05

alex


2 Answers

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);
like image 169
Quentin Avatar answered Oct 14 '22 00:10

Quentin


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);
like image 42
RobG Avatar answered Oct 14 '22 02:10

RobG