this, call, apply & bind
Key Learning Objectives
Master the 4 core binding rules of JavaScript 'this': default, implicit, explicit, and new.
Understand why extracting an object method loses implicit context (the unbound function trap).
Grasp hard binding with Function.prototype.bind and why subsequent .call() or .apply() cannot override it.
Recognize lexical this resolution in arrow functions and why they ignore explicit binding methods.
The Interview Problem
What is printed to the console when the following JavaScript code executes, and how do explicit binding and arrow functions alter the value of 'this'?
1const obj = {2 name: 'Alice',3 regular() {4 return this.name;5 },6 getArrow() {7 return () => this.name;8 },9};1011const bob = { name: 'Bob' };12const charlie = { name: 'Charlie' };1314const extracted = obj.regular;15const bound = obj.regular.bind(bob);16const nestedArrow = obj.getArrow();1718console.log(19 obj.regular(),20 extracted.call(charlie),21 bound.call(charlie),22 nestedArrow.call(charlie)23);
Predict Console Output
Select the option that matches what standard ECMAScript prints to the console:
Alice Charlie Bob Alice
Alice Charlie Charlie Charlie
Alice undefined Bob undefined
Alice Charlie Bob Bob
V8 Engine Execution Trace
Step 1 of 8 (Line 1)Global Execution Context allocates obj, bob, and charlie in heap memory. obj exposes regular() and getArrow() methods.
Deep Technical Breakdown
The 4 Rules of 'this' Binding in JavaScript
Unlike lexical scope which is determined at author time, this in standard JavaScript functions is bound dynamically based entirely on the call-site (how the function is invoked):
- Default Binding: Standalone function invocation (e.g.
fn()). In non-strict mode,thisis the global object (windoworglobal). In strict mode ('use strict'),thisisundefined. - Implicit Binding: Method invocation preceded by an object reference (e.g.
obj.fn()).thisis the containing objectobj. - Explicit Binding: Invoking via
Function.prototype.call(thisArg, ...args)orFunction.prototype.apply(thisArg, [args]). ForcesthistothisArg. - Hard Binding (.bind):
fn.bind(thisArg)returns an ECMAScript Exotic Bound Function Object. Its internal[[BoundThis]]slot permanently storesthisArg. Any subsequent attempts to rebind it via.call(),.apply(), or another.bind()are completely ignored.
The Arrow Function Exception: Lexical this
Arrow functions do NOT have their own this binding ([[ThisMode]]: lexical). They resolve this like any regular variable by walking up the lexical scope chain to the enclosing execution context at the moment of creation. Because they have no internal this slot, call(), apply(), and bind() have no effect on their context.
Common Traps & Mistakes
Believing that chaining `.bind()` works: `fn.bind(a).bind(b)` will ALWAYS bind `this` to `a`, never `b`.
Assuming arrow functions declared inside object literals bind to the object: object literals do NOT create a lexical scope; only functions, blocks, and modules do.
Passing an object method as a callback (e.g., `setTimeout(obj.method, 1000)`), which detaches the method and falls back to default binding.
FAANG Follow-Up Probes
Probe #1
How does the `new` operator interact with a hard-bound function created via `.bind()` (precedence of `new` over `bind`)?
Probe #2
How would you implement a polyfill for `Function.prototype.bind` supporting partial application and `new` instantiation?
Probe #3
What is the difference between `call` and `apply` in V8 performance and argument spreading?
