Quick Overview
`this` is decided by how a function is called, not where it was defined: `user.greet()` binds `user`, while calling it alone binds `undefined`. Arrow functions inherit the enclosing scope.
In JavaScript, the this keyword refers to an object context, but which object depends on how the function was invoked at runtime!
Losing this context inside event handlers or async callbacks is a frequent bug when object methods are detached.
this Bindingobj.method()) -> this refers to obj.fn.call(obj), fn.apply(obj), or fn.bind(obj).new Constructor() -> this refers to the newly instantiated object.this. They inherit this lexically from their outer parent scope!const user = {
name: "Maria",
greet() {
console.log(`Hi, I am ${this.name}`);
},
};
user.greet(); // "Hi, I am Maria" (Implicit)
const detachedGreet = user.greet;
detachedGreet(); // "Hi, I am undefined" (Lost context!)
// Explicit Fix using .bind()
const boundGreet = user.greet.bind(user);
boundGreet(); // "Hi, I am Maria"
thisArrow functions capture this from their enclosing lexical context:
const timer = {
seconds: 0,
start() {
setInterval(() => {
this.seconds++; // Inherits 'this' from timer object!
console.log(this.seconds);
}, 1000);
},
};
this to point to the object, because arrow functions capture outer global this!Write it yourself. The tests below run against your code.
Always check how the function was invoked. Next, let's learn how the V8 Event Loop handles Microtasks vs Macrotasks!
Primitives copy by value and objects copy by reference, so `b = a` duplicates a number but shares an object. That single distinction explains most surprise mutations in a codebase.
`const` prevents reassignment, not mutation: a `const` object's properties can still be changed. `let` is scoped to its block, while `var` is function-scoped and leaks out of loops.
Only backticks interpolate: `${user}` reads the variable, while the identical text in quotes prints literally. Strings are immutable, so every method returns a new one rather than editing in place.