The 'this' Keyword
The this
keyword refers to the object that is currently executing the code. Its value depends on how and where a function is called.
Global Context
javascript// In global scope, 'this' refers to the global object console.log(this); // Window object in browser, global in Node.js function globalFunction() { console.log(this); // Window object (or undefined in strict mode) } globalFunction(); // Strict mode "use strict"; function strictFunction() { console.log(this); // undefined }
Object Method Context
javascriptconst person = { name: "Alice", age: 30, greet: function() { console.log(`Hello, I'm ${this.name}`); // 'this' refers to person }, getInfo: function() { return `${this.name} is ${this.age} years old`; } }; person.greet(); // "Hello, I'm Alice" console.log(person.getInfo()); // "Alice is 30 years old"
Arrow Functions and 'this'
javascriptconst obj = { name: "Bob", regularMethod: function() { console.log("Regular:", this.name); // "Bob" const innerArrow = () => { console.log("Arrow inside regular:", this.name); // "Bob" }; innerArrow(); }, arrowMethod: () => { console.log("Arrow method:", this.name); // undefined (inherits from global) } }; obj.regularMethod(); obj.arrowMethod();
Constructor Functions
javascriptfunction Person(name, age) { this.name = name; // 'this' refers to the new instance this.age = age; this.greet = function() { console.log(`Hi, I'm ${this.name}`); }; } const person1 = new Person("Charlie", 25); const person2 = new Person("Diana", 28); person1.greet(); // "Hi, I'm Charlie" person2.greet(); // "Hi, I'm Diana"
Event Handlers
javascriptconst button = document.querySelector('#myButton'); // Regular function - 'this' refers to the button button.addEventListener('click', function() { console.log(this); // The button element this.style.backgroundColor = 'blue'; }); // Arrow function - 'this' refers to outer scope button.addEventListener('click', () => { console.log(this); // Window object (not the button) }); // Object method as event handler const handler = { color: 'red', handleClick: function() { console.log(this.color); // "red" } }; // Need to bind 'this' when using object methods button.addEventListener('click', handler.handleClick.bind(handler));
Common 'this' Problems
javascriptconst user = { name: "Eve", greet: function() { console.log(`Hello, ${this.name}`); } }; // Problem: Lost context const greetFunction = user.greet; greetFunction(); // "Hello, undefined" - 'this' is not user // Problem: Callback functions setTimeout(user.greet, 1000); // "Hello, undefined" // Solutions: // 1. Use bind setTimeout(user.greet.bind(user), 1000); // "Hello, Eve" // 2. Use arrow function wrapper setTimeout(() => user.greet(), 1000); // "Hello, Eve" // 3. Store reference to 'this' const userGreet = { name: "Frank", greet: function() { const self = this; // Store reference setTimeout(function() { console.log(`Hello, ${self.name}`); }, 1000); } };
Class Context
javascriptclass Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a sound`); } delayedSpeak() { // Arrow function preserves 'this' setTimeout(() => { this.speak(); }, 1000); } } const dog = new Animal("Rex"); dog.speak(); // "Rex makes a sound" dog.delayedSpeak(); // "Rex makes a sound" (after 1 second)
Practical Examples
javascript// Shopping cart example const shoppingCart = { items: [], total: 0, addItem: function(item) { this.items.push(item); this.updateTotal(); }, removeItem: function(itemId) { this.items = this.items.filter(item => item.id !== itemId); this.updateTotal(); }, updateTotal: function() { this.total = this.items.reduce((sum, item) => sum + item.price, 0); }, getInfo: function() { return `Cart has ${this.items.length} items, total: $${this.total}`; } }; // Counter with methods function createCounter(initialValue = 0) { return { value: initialValue, increment: function() { this.value++; return this; }, decrement: function() { this.value--; return this; }, getValue: function() { return this.value; } }; } const counter = createCounter(5); console.log(counter.increment().increment().getValue()); // 7