One of the most confusing aspects of JavaScript for me was understanding how the this keyword works.
The this keyword in JavaScript behaves differently from OOP languages like C#, Java, or Python (where the equivalent is self) because of how this is determined. In those languages, this consistently refers to the current instance of the class or object. In JavaScript, however, this is more dynamic and its value depends on how and where a function is invoked.
With that in mind, I decided to create a summary of the different scenarios where the behavior of this can vary. Here's the breakdown:
1. Global Context
Non-Strict Mode:
-
thisrefers to the global object (windowin browsers,globalin Node.js).
console.log(this); // `window` or `global`
Strict Mode:
-
thisisundefined.
"use strict";
console.log(this); // undefined
2. Inside a Function
Regular Function:
- In non-strict mode,
thisrefers to the global object. - In strict mode,
thisisundefined.
function myFunction() {
console.log(this);
}
myFunction(); // `window` (non-strict), undefined (strict)
3. As a Method of an Object
- When a function is called as a method of an object,
thisrefers to the object that owns the method.
const obj = {
name: "JavaScript",
greet() {
console.log(this.name); // `this` refers to `obj`
}
};
obj.greet(); // Output: "JavaScript"
4. Arrow Functions
- Arrow functions do not have their own
this. Instead, they inheritthisfrom their lexical scope (the surrounding context).
const obj = {
name: "JavaScript",
arrowFunc: () => {
console.log(this.name); // `this` is inherited from the global scope
}
};
obj.arrowFunc(); // undefined (in browsers, `this` is `window`)
function outer() {
const arrow = () => console.log(this);
arrow(); // Inherits `this` from `outer`'s context
}
outer();
5. In a Constructor
- In a constructor function or class,
thisrefers to the instance being created.
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}`);
}
}
const person = new Person("Alice");
person.greet(); // Output: Hello, Alice
6. Explicit Binding (call, apply, bind)
In JavaScript, functions are objects and have methods like call, apply, and bind, which let you explicitly set the value of this.
call and apply:
-
Invoke the function with a specified
thisvalue. - Difference:
callaccepts arguments as a comma-separated list;applytakes an array.
function greet(greeting) {
console.log(`${greeting}, ${this.name}`);
}
const user = { name: "Alice" };
greet.call(user, "Hello"); // Output: Hello, Alice
greet.apply(user, ["Hi"]); // Output: Hi, Alice
bind:
-
Returns a new function with
thispermanently bound to the specified value.
const boundGreet = greet.bind(user);
boundGreet("Hello"); // Output: Hello, Alice
7. In an Event Listener
Regular Function:
-
thisrefers to the element that triggered the event.
const button = document.querySelector("button");
button.addEventListener("click", function () {
console.log(this); // The button element
});
Arrow Function:
-
thisinherits from the surrounding scope, not the element.
button.addEventListener("click", () => {
console.log(this); // `this` depends on where the arrow function is defined
});
8. Inside setTimeout or setInterval
Regular Function:
-
thisdefaults to the global object (window).
setTimeout(function () {
console.log(this); // `window` in browsers
}, 1000);
Arrow Function:
- Inherits
thisfrom its lexical scope.
setTimeout(() => {
console.log(this); // Inherits `this` from the surrounding context
}, 1000);
9. In Classes
- Inside a class method,
thisrefers to the class instance.
class MyClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
const obj = new MyClass("JavaScript");
obj.sayName(); // Output: JavaScript
10. Losing Context (Method Extraction)
When a method is assigned to a variable or passed as a callback, this can lose its binding.
const obj = {
name: "JavaScript",
greet() {
console.log(this.name);
}
};
const greet = obj.greet;
greet(); // undefined (`this` is no longer bound to `obj`)
Solutions:
- Use
bind:
const boundGreet = obj.greet.bind(obj);
boundGreet(); // Output: JavaScript
- Use an Arrow Function:
const obj = {
name: "JavaScript",
greet: () => console.log(this.name) // `this` is inherited lexically
};
obj.greet(); // Output depends on outer scope
11. In new Keyword Usage
When you use new with a function or class, this refers to the newly created object.
function MyConstructor() {
this.name = "New Object";
}
const instance = new MyConstructor();
console.log(instance.name); // Output: New Object
Summary
| Context |
this Refers To |
|---|---|
| Global (non-strict) | Global object (window/global). |
| Global (strict) |
undefined. |
| Object Method | The object that owns the method. |
| Arrow Function | Inherits this from the enclosing context. |
| Constructor/Class | The instance being created. |
call, apply, bind
|
Explicitly defined value. |
| Event Listener | The element that triggered the event. |
setTimeout/Interval |
Global object or inherited context (arrow). |
new Keyword |
The newly created object. |
Top comments (0)