The this keyword
Resolve this from the call site across constructor, explicit, implicit, default, bound, and lexical arrow-function behavior.

WHAT YOU WILL BE ABLE TO DO
Learning outcomes
- Explain the this keyword in plain language.
- Connect the behavior to the underlying browser or framework model.
- Implement the core pattern and reason through edge cases.
- Answer common follow-ups without relying on memorized phrases.
01Overview
this is not determined by where a function is defined; it's determined by how the function is called — the call site.
02Mental model
- new binding: calling with new makes this the newly created object (highest precedence).
- Explicit binding: call, apply, or bind set this directly.
- Implicit binding: obj.method() sets this to obj.
- Default binding: a bare function call gets this as undefined (strict mode) or the global object.
- Arrow functions ignore all of the above and use this from their enclosing lexical scope.
03Examples
const user = { name: 'Ada', greet() { return `Hi, ${this.name}`; },};const greet = user.greet;greet(); // this is undefined/global — 'name' lookup fails
const bound = user.greet.bind(user);bound(); // 'Hi, Ada'04Check understanding
Why does extracting a method and calling it standalone break this?
Extraction discards the call-site: obj.method() implicitly binds this to obj, but a bare reference invoked alone falls back to default binding.
DDConcept deep dives
Deep dive 1
Ordinary-function this comes from the call expression
Look at how the function is invoked, not where its source appears. A constructor call creates a new receiver; call, apply, or bind supplies one explicitly; a member call supplies its base object; a plain strict-mode call supplies undefined. These rules have precedence, and losing the member call by extracting a method loses its implicit receiver.
- obj.method() and const m = obj.method; m() are different call forms.
- Callback APIs decide how they invoke an ordinary function.
- Destructuring a method does not preserve its original object.
Deep dive 2
Arrow functions inherit this
An arrow does not define its own this, arguments, super, or new.target bindings. It resolves them from the surrounding lexical environment. That makes it convenient inside a method callback that should retain the method's receiver, but it also means call, apply, and bind cannot provide a different receiver and the arrow cannot be used as a constructor.
- A class-field arrow creates a new function for each instance.
- An arrow used as an object-literal method usually captures an outer this, not the object.
- Lexical this removes call-site flexibility intentionally.
Deep dive 3
API design can remove receiver ambiguity
Dynamic this is useful when behavior is intentionally shared across receivers, as with prototype methods. For many utilities, an explicit object parameter or closure makes dependencies clearer. In UI callbacks, binding once produces stable identity for registration and removal; creating bind or an inline wrapper at both boundaries produces different functions and cleanup fails.
- Choose receiver-based methods when object identity is part of the abstraction.
- Prefer explicit dependencies for pure transformation logic.
- Retain the exact callback reference required by removeEventListener.
QAInterview questions and model answers
Attempt each answer aloud before opening it. The model answer shows the depth and precision expected in an interview; it is not a script to memorize.
Intermediate · Coding · 1 min · Question 1How is this determined in JavaScript?Open model answer
Model answer
For ordinary functions, this is determined by the call form: new binding, explicit call/apply/bind, method-style implicit binding, or the default rule. Arrow functions do not create their own this; they resolve it lexically from the surrounding scope.
function whoAmI() { return this; }
whoAmI(); // undefined (strict) or global (sloppy) — defaultwhoAmI.call({ id: 1 }); // { id: 1 } — explicitconst o = { whoAmI };o.whoAmI(); // o — implicit (method call)new whoAmI(); // the new instance — new bindingIntermediate · Coding · 1 min · Question 2Why does const f = object.method; f() lose the object?Open model answer
Model answer
The reference is extracted and then called as a plain function, so the member-call base object is no longer part of the call expression. Bind the method, wrap it in another function, or design the API so it does not depend on dynamic this.
const user = { name: 'Ada', greet() { return `Hi ${this.name}`; } };
const g = user.greet;g(); // "Hi undefined" — call site has no base objectconst bound = user.greet.bind(user);bound(); // "Hi Ada"Intermediate · Conceptual · 1 min · Question 3What does bind return?Open model answer
Model answer
bind creates a new function with permanently associated this and optional leading arguments. Calling it with call or apply cannot replace the bound this. When invoked with new, constructor semantics take precedence for the created instance.
Open question page →Intermediate · Coding · 1 min · Question 4How does this behave in arrow functions?Open model answer
Model answer
An arrow captures this from its lexical environment and ignores call, apply, and bind attempts to replace it. That makes arrows useful for callbacks needing the enclosing instance, but unsuitable as dynamically bound object methods or constructors.
const timer = { seconds: 0, start() { setInterval(() => { this.seconds++; }, 1000); // arrow: `this` is `timer` },};// A regular function here would get its own `this` (undefined/global).Intermediate · Conceptual · 1 min · Question 5What is default this in strict mode?Open model answer
Model answer
A plain call to an ordinary strict-mode function receives undefined. In sloppy mode it may substitute the global object and box primitives. ES modules and class bodies use strict semantics, so relying on sloppy default binding is fragile.
Open question page →Intermediate · Conceptual · 1 min · Question 6Does this point to the function that is running?Open model answer
Model answer
No. this is a call-time value, not a pointer to the current function or necessarily the object where the function was defined. Lexical arrows are the exception in the sense that they inherit the surrounding this.
Open question page →Advanced · Conceptual · 1 min · Question 7How does new interact with an explicitly returned object?Open model answer
Model answer
If a constructor explicitly returns an object, that object replaces the newly created receiver. Returning a primitive does not replace the constructed instance.
Open question page →Intermediate · Conceptual · 1 min · Question 8What is this inside a class static method?Open model answer
Model answer
A static method is called on the class constructor, so an ordinary member call binds this to that constructor or the subclass used as the receiver.
Open question page →Beginner · Conceptual · 1 min · Question 9Can an arrow function be used with new?Open model answer
Model answer
No. Arrow functions lack [[Construct]] and their own prototype property for instance construction, so calling one with new throws a TypeError.
Open question page →Advanced · Conceptual · 1 min · Question 10How does super relate to this in a derived constructor?Open model answer
Model answer
A derived constructor cannot access this before calling super. super initializes the inherited instance receiver, after which the constructor may use this.
Open question page →SCScenario questions
Scenario 1
A class method passed directly as a click callback crashes because this is undefined. Compare fixes.
- Identify the lost receiver at the callback boundary.
- Consider binding once in construction, a class-field arrow, or a wrapper at registration.
- Ensure removal uses the same function identity.
- Question whether the method needs this at all.
Reveal worked answer
Binding once preserves a stable callback identity but creates one bound function per instance. A class-field arrow also creates per-instance state and lexical this. An inline wrapper is simple but must be retained if removal is required. A pure function receiving explicit data avoids this coupling entirely.