DaddyMike
DaddyMike

Reputation: 161

Arrow function in setTimeout doesn't set window as this

I have some method of an object assigned by a decorator (that's where the function f, and ms are taken from).

  function() {
        setTimeout(() => f.apply(this, arguments), ms); 
      };

'this' refers here to the object. But 'this' of setTimeout is window, not that object. If 'this' of an arrow function is taken lexically, then how come it's not taken from setTimeout? After all, in the following code:

let user = {
  firstName: "Ilya",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi(); // Ilya

'this' is taken from the function above. So if that function is setTimeout in the first situation why aren't both situations the same? I thought it might have had something to do with the function being passed as argument in one case, and in the other one as a local variable, but wouldn't this come down to the same in lexical environments?

Why is there a difference?

Besides, to test this out:

let obj = {name : "Jeff"};
let obj2 = {name : "Bart", fun2 : function(fun){fun();}};

obj.name2 = obj2.fun2(() => alert(this.name));

but now I don't get "Bart" alerted, but an empty string. When I replace "name" with length, I just get 0, the 'this' refers to the window.

Why doesn't this work as intended?

Upvotes: 1

Views: 821

Answers (2)

Vicky Gonsalves
Vicky Gonsalves

Reputation: 11717

Inside a function, the value of this depends on how the function is called.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

function f1() {
  return this;
}

// In a browser:
f1() === window; // true

In your function you have passed the window object to the setTimeout.

If you alter you function and pass just arguments you will get the object:

function f() {
  console.log(this);
};

function a (){
  setTimeout(() => f.apply([1]), 1000); // here this = [1]
}

a();  // Array [1]

Upvotes: 0

Quentin
Quentin

Reputation: 943635

If 'this' of an arrow function is taken lexically, then how come it's not taken from setTimeout?

Lexical means that the scope is taken from where the function is declared, not where it is passed to.

Upvotes: 2

Related Questions