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:
-
this
refers to the global object (window
in browsers,global
in Node.js).
console.log(this); // `window` or `global`
Strict Mode:
-
this
isundefined
.
"use strict";
console.log(this); // undefined
2. Inside a Function
Regular Function:
- In non-strict mode,
this
refers to the global object. - In strict mode,
this
isundefined
.
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,
this
refers 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 inheritthis
from 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,
this
refers 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
this
value. - Difference:
call
accepts arguments as a comma-separated list;apply
takes 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
this
permanently bound to the specified value.
const boundGreet = greet.bind(user);
boundGreet("Hello"); // Output: Hello, Alice
7. In an Event Listener
Regular Function:
-
this
refers to the element that triggered the event.
const button = document.querySelector("button");
button.addEventListener("click", function () {
console.log(this); // The button element
});
Arrow Function:
-
this
inherits 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:
-
this
defaults to the global object (window
).
setTimeout(function () {
console.log(this); // `window` in browsers
}, 1000);
Arrow Function:
- Inherits
this
from its lexical scope.
setTimeout(() => {
console.log(this); // Inherits `this` from the surrounding context
}, 1000);
9. In Classes
- Inside a class method,
this
refers 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)