What does this this-binding snippet print, and why?
What does the following code print, and why? (Run in non-strict mode, in a browser, name not assigned globally.)
const obj = {
name: 'obj',
method() { console.log(this.name); },
arrow: () => console.log(this.name),
};
obj.method();
const fn = obj.method;
fn();
obj.arrow();
setTimeout(obj.method, 0);
Predict the output and explain.
It prints obj, then '' three times. this is set by the call site, not where the function is defined. obj.method() binds this to obj. The detached fn() and the setTimeout callback are plain calls, so this is the global object (window.name is ''). The arrow has no own this; it inherits the module's outer this, also giving ''.
- ✗Thinking
thisis fixed at definition rather than set by the call site - ✗Assuming an arrow inside an object literal binds
thisto that object - ✗Expecting a detached method to keep its original receiver
- →How would the detached
fn()behave differently in strict mode? - →How does passing
obj.method.bind(obj)tosetTimeoutchange the output?
Solution
this is determined by HOW a function is called, not where it is declared; an arrow has no own this.
obj.method(); // 'obj' — called as a method of obj
const fn = obj.method;
fn(); // '' — plain call, this = global object
obj.arrow(); // '' — arrow inherits the outer this
setTimeout(obj.method, 0); // '' — callback called with no receiver
How it works
obj.method() is called with the receiver obj, so this.name is 'obj'.
const fn = obj.method; fn() is a plain call with no receiver. In non-strict mode this falls back to the global object (window), and window.name is ''. The same happens with setTimeout(obj.method, 0): the timer calls the function with no obj on the left, so there is no receiver.
obj.arrow is an arrow function; it has no this of its own and takes it from the outer scope where the literal is defined (module/top level), which also gives ''. The arrow's binding does not depend on it being written inside the object. </content>