Hello everyone! I’d like to ask something about losing this when calling an object’s method. I understand that this is evaluated at running time (this = the object -aka context- that called the function) and we cannot change that (unless we use an explicit binding, like bind, call or apply). I understand, also, that arrow functions have no this, which is always taken from the outer scope (in pseudo code we could say: find out where the function/method we’re calling was defined, and use that context as this)… Yet, I’m a bit confused about this snippet of code:
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
setTimeout(user.sayHi, 1000); // Hello, undefined!
//While:
setTimeout(function() {
user.sayHi(); // Hello, John!
}, 1000);
//And with arrow function:
setTimeout(() => user.sayHi(), 1000); // Hello, John!
//To understand it better, I can picture it this way
let func = user.sayHi; //I assign to a variable a reference to the user's *sayHi* method
console.log(func) //[Function: sayHi]
func(); /* TypeError: this is undefined;
*/
That’s because I got just the function (sayHi), as I’d cut it from the object, right? So when I call it the function (obviously) tries to retrieve the value of this, but there is not context, no object calling it at all, right? Or it’s because the context is considered the window object, where we don’t have a firstName property? (It’d work anyway in strict-mode, even with a variable firstName in the global scope)
//This, in non-strict, this snippet works:
name = 'Jack';
function test(){
console.log(this.name)
}
test() //Jack
What happens with the setTimeout snippet, exactly? If I’m not wrong, setTimeout uses the window object by default, so setTimeout(user.sayHi, 1000)
is like saying ‘get the property firstName from the global scope’, where obviously we don’t have one. Why, then, a wrapper like setTimeout(function() { user.sayHi(); // Hello, John! }, 1000);
works? I’m really confused, could someone help me in figuring that out please?