How does the this keyword work in JavaScript?

JavaScript ImportantSwiggyPegasystems

this keyword

The this keyword in JavaScript is a special keyword that refers to the current context in which code is being executed. Think of it as a reference to the "owner" of the currently executing code.

The this keyword allows you to reuse functions with different contexts.

I'll break down each scenario in more detail to help you understand how this behaves in different contexts.

Global Context & Strict Mode

function showThis() {
console.log(this);
}

// Call site 1: Direct invocation
showThis(); // Output: Window {...}
// WHY: When a function is called without any context (not as a method),
// 'this' defaults to the global object (Window in browsers)

// Call site 2: Strict mode
('use strict');
function strictShowThis() {
console.log(this);
}
strictShowThis(); // Output: undefined
// WHY: Strict mode changes this behavior to prevent accidental global object access.
// It makes 'this' undefined instead of defaulting to global object.

Object Method Context

const person = {
name: 'John',
sayHi: function () {
console.log('Hi, I am ' + this.name);
},
};

// Call site 1: Method invocation
person.sayHi(); // Output: "Hi, I am John"
// WHY: When a method is called directly on an object, 'this' binds to that object.
// The call site shows person.sayHi(), so JavaScript knows to bind 'this' to person.

// Call site 2: Function reference
const greet = person.sayHi;
greet(); // Output: "Hi, I am undefined"
// WHY: We've lost the object context! When we assign the function to a new variable,
// we're just getting the function itself, without its original object binding.
// The call site is now just greet(), so 'this' defaults to global/undefined.

Constructor Functions

function User(name) {
this.name = name;
this.sayName = function () {
console.log('My name is ' + this.name);
};
}

// Call site 1: With 'new' keyword
const user1 = new User('John');
user1.sayName(); // Output: "My name is John"
// WHY: The 'new' keyword creates a new empty object and makes 'this' point to it.
// It's like saying "create a new context for this function"

// Call site 2: Without 'new' (wrong!)
const user2 = User('Jane');
// WHY: Without 'new', it's a regular function call, so 'this' points to global
// This accidentally sets window.name = "Jane" - a common mistake!

Event Listeners

const button = document.createElement('button');

button.addEventListener('click', function () {
console.log(this); // Output: <button> element
});
// WHY: DOM events automatically bind 'this' to the element that triggered the event.
// This is built into how addEventListener works.

button.addEventListener('click', () => {
console.log(this); // Output: Window or parent scope's 'this'
});
// WHY: Arrow functions are different! They inherit 'this' from their enclosing scope.
// They don't get their own 'this' binding.

Explicit Binding (bind/call/apply)

function introduce() {
console.log('I am ' + this.name);
}

const person1 = { name: 'John' };
const person2 = { name: 'Jane' };

// Call site 1: Using call/apply
introduce.call(person1); // Output: "I am John"
introduce.apply(person2); // Output: "I am Jane"
// WHY: call/apply let you explicitly set what 'this' should be.
// It's like saying "run this function, but pretend it belongs to this object"

// Call site 2: Using bind
const introducePerson1 = introduce.bind(person1);
introducePerson1(); // Output: "I am John"
// WHY: bind creates a new function with 'this' permanently set to the specified object.
// It's like creating a copy of the function that always remembers its context.

Key Points

  • JavaScript determines this at runtime based on the call site (how the function is called)
  • The value of this is not determined by where the function is defined, but by how it's called
  • Arrow functions are special - they inherit this from their surrounding scope
  • Explicit binding methods (call, apply, bind) let you control what this refers to
  • The new keyword creates a fresh context, making this point to the new object

This design allows for flexible function reuse and method borrowing, but it can also lead to confusion if you're not careful about how functions are called.

00:00