Output: The 'this' Keyword
TL;DR
this output questions test whether you understand the difference between Implicit Binding (object methods), Default Binding (bare function calls), and Lexical Binding (Arrow functions).
Question 1: The Method Trap
const user = {
name: "Alice",
greet() {
return `Hello, ${this.name}`;
}
};
const sayHello = user.greet;
console.log(user.greet());
console.log(sayHello());
Output:
"Hello, Alice"
"Hello, undefined" // (Or an error in Strict Mode)
Why?
The this keyword is NOT determined by where the function was written. It is determined purely by how it is called.
user.greet()is called with a dot. Implicit binding applies.thisequalsuser.sayHello()is called bare. There is no dot to its left. Default binding applies.thisequals the globalwindowobject.window.nameis undefined.
Question 2: Arrow Functions in Objects
const obj = {
id: 42,
traditional: function() {
console.log(this.id);
},
arrow: () => {
console.log(this.id);
}
};
obj.traditional();
obj.arrow();
Output:
42
undefined
Why?
Arrow functions completely ignore the “dot” rule. They do not bind their own this. They inherit this from their parent Lexical Scope. Object literals {} do not create a scope in JavaScript. So the arrow function looks past the object directly to the Global Scope. window.id is undefined. Never use arrow functions as object methods.
Question 3: The Callback Context
const worker = {
task: "Build House",
doWork() {
setTimeout(function() {
console.log(`Working on: ${this.task}`);
}, 100);
}
};
worker.doWork();
Output:
"Working on: undefined"
Why?
This is a classic bug. worker.doWork() correctly sets this to worker inside the doWork function. However, the setTimeout callback is a completely different function. When the timer finishes, the browser’s Event Loop pulls the callback from the Macrotask Queue and executes it bare. Since it’s called bare, this defaults to window.
(Fix: Use an arrow function for the setTimeout callback () => { ... }. The arrow function will look up the scope chain, find doWork(), and borrow its worker context).
Question 4: Binding Precedence
function show() {
console.log(this.val);
}
const obj1 = { val: 1 };
const obj2 = { val: 2 };
const boundFunc = show.bind(obj1);
boundFunc.call(obj2);
Output:
1
Why?
Once a function is bound using .bind(), its this context is permanently locked forever. You cannot override it by using .call(), .apply(), or even another .bind(). The JavaScript engine ignores the attempt to bind it to obj2.