this and Context
What is this?
Section titled “What is this?”this is a special keyword that refers to the execution context — the object that is considered the receiver of the current function call. Unlike most languages, this in JavaScript is not bound at definition time; it is determined at call time by how the function is invoked.
this in different call patterns
Section titled “this in different call patterns”// 1. Method call — this is the object before the dotconst user = { name: 'Alice', greet: function() { return 'Hi, I am ' + this.name; },};console.log(user.greet()); // 'Hi, I am Alice'
// 2. Plain function call — this is undefined (strict mode) or globalThisfunction whoAmI() { return typeof this; // 'undefined' in strict mode}
// 3. Constructor call — this is the newly created objectfunction Person(name) { this.name = name;}const p = new Person('Bob');console.log(p.name); // 'Bob'Losing this
Section titled “Losing this”The most common pitfall: extracting a method from an object loses the binding.
const timer = { label: 'tick', start: function() { // After 0 ms, fn is called as a plain function — this.label is undefined setTimeout(function() { console.log(this.label); // undefined — 'this' is not timer }, 0); },};call, apply, and bind
Section titled “call, apply, and bind”These three methods let you explicitly set this.
function introduce(greeting, punctuation) { return greeting + ', I am ' + this.name + punctuation;}
const obj = { name: 'Carol' };
// call — pass arguments individuallyintroduce.call(obj, 'Hello', '!'); // 'Hello, I am Carol!'
// apply — pass arguments as an arrayintroduce.apply(obj, ['Hey', '.']); // 'Hey, I am Carol.'
// bind — returns a NEW function with this permanently boundconst boundIntroduce = introduce.bind(obj);boundIntroduce('Hi', '?'); // 'Hi, I am Carol?'Arrow functions and this
Section titled “Arrow functions and this”Arrow functions do not have their own this. They inherit this from the lexical enclosing scope — the surrounding regular function or module scope at the point where they are written.
const timer2 = { label: 'tick', start: function() { // Arrow function inherits 'this' from start() — which is timer2 setTimeout(() => { console.log(this.label); // 'tick' — correctly bound }, 0); },};This makes arrow functions the natural choice for callbacks inside methods.