The this keyword in JavaScript is one of the most confusing concepts for beginners. Unlike many other programming languages, the value of this in JavaScript is not always determined by where a function is written.
Instead, the value of this depends mainly on how a function is called.
Understanding the JavaScript this keyword is important when working with objects, functions, classes, event handlers, constructors, and modern JavaScript frameworks.
In this guide, we’ll explain what this means in JavaScript, how the this keyword works, this in objects, regular functions, arrow functions, constructors, classes, event handlers, call(), apply(), and bind(), with practical examples.
What Is the this Keyword in JavaScript?
The this keyword refers to a value that depends on the context in which a function is executed.
Consider this example:
const user = {
name: "John",
greet() {
console.log(this.name);
}
};
user.greet();
Output:
John
Here, this refers to the user object.
Therefore:
this.name
is equivalent to:
user.name
But this doesn’t always refer to the object where the function was created.
That’s where JavaScript’s behavior becomes interesting.
How Does this Work in JavaScript?
The most important rule to remember is:
In regular functions, the value of
thisis generally determined by how the function is called.
For example:
const user = {
name: "John",
greet() {
console.log(this.name);
}
};
user.greet();
Here:
user.greet()
means that this refers to user.
But if we separate the function:
const greet = user.greet;
greet();
the behavior changes because the function is no longer being called as:
user.greet()
This is why understanding the call site is important when working with this.
JavaScript this in the Global Context
The value of this at the top level depends on the JavaScript environment and whether you’re using a script or an ES module.
In a browser’s traditional script:
console.log(this);
this refers to the global object, which is typically:
window
For example:
console.log(this === window);
Output:
true
However, JavaScript modules behave differently.
This distinction is important because modern applications commonly use ES modules.
this in Regular Functions
Consider a regular function:
function showThis() {
console.log(this);
}
showThis();
The value of this depends on the execution mode.
In strict mode, a standalone regular function call has:
this === undefined
For example:
"use strict";
function showThis() {
console.log(this);
}
showThis();
Output:
undefined
This is one reason strict mode can make JavaScript behavior more predictable.
this in Objects
One of the most common uses of this is inside object methods.
const person = {
name: "Alice",
sayHello() {
console.log(`Hello, ${this.name}`);
}
};
person.sayHello();
Output:
Hello, Alice
Here:
this
refers to the object used to call the method.
Therefore:
person.sayHello();
causes:
this === person
inside the method.
Another Example
const car = {
brand: "Toyota",
showBrand() {
console.log(this.brand);
}
};
car.showBrand();
Output:
Toyota
The important point is that this refers to the calling object, not simply the object in which the function was originally written.
this in Nested Functions
A common source of confusion occurs when a regular function is nested inside an object method.
const user = {
name: "John",
greet() {
function innerFunction() {
console.log(this);
}
innerFunction();
}
};
user.greet();
The this inside innerFunction() does not automatically refer to user.
That’s because innerFunction() is called as a standalone function.
One common solution is to use an arrow function:
const user = {
name: "John",
greet() {
const innerFunction = () => {
console.log(this.name);
};
innerFunction();
}
};
user.greet();
Output:
John
This works because arrow functions don’t create their own this.
this in Arrow Functions
Arrow functions are one of the most important concepts when learning the JavaScript this keyword.
Arrow functions do not have their own this.
Instead, they inherit this from their surrounding lexical scope.
For example:
const user = {
name: "John",
greet() {
const sayName = () => {
console.log(this.name);
};
sayName();
}
};
user.greet();
Output:
John
The arrow function inherits this from greet().
Regular Function vs Arrow Function
Regular function:
function greet() {
console.log(this);
}
Arrow function:
const greet = () => {
console.log(this);
};
A regular function gets its this based on how it is called.
An arrow function captures this from its surrounding scope.
This difference is extremely important in JavaScript.
Why Arrow Functions Don’t Have Their Own this
Consider:
const user = {
name: "John",
greet: () => {
console.log(this.name);
}
};
user.greet();
Many beginners expect:
John
But that isn’t how arrow functions work.
The arrow function doesn’t create its own this.
Instead, it uses the surrounding lexical this.
Therefore, arrow functions are generally not a replacement for object methods when you need dynamic method this.
A better approach is:
const user = {
name: "John",
greet() {
console.log(this.name);
}
};
this in Constructor Functions
Before JavaScript classes became common, constructor functions were widely used to create objects.
For example:
function User(name) {
this.name = name;
}
const user1 = new User("John");
console.log(user1.name);
Output:
John
When a function is called with the new keyword, this refers to the newly created object.
Conceptually:
new User("John")
↓
Create new object
↓
this → new object
↓
Set properties
Therefore:
this.name = name;
sets the name property on the newly created object.
this in JavaScript Classes
The same concept applies to JavaScript classes.
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}`);
}
}
const user = new User("John");
user.greet();
Output:
Hello, John
Inside the constructor:
this
refers to the newly created instance.
So:
this.name = name;
creates an instance property.
this in Class Methods
Consider:
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(this.name);
}
}
const user = new User("Alice");
user.greet();
Here:
this === user
when greet() is called as:
user.greet();
However, extracting the method can change the call context:
const greet = user.greet;
greet();
The method is no longer being called as a property of user, so you should not assume this will still refer to the instance.
this With call()
JavaScript provides the call() method to explicitly specify the value of this.
For example:
function greet() {
console.log(`Hello, ${this.name}`);
}
const user = {
name: "John"
};
greet.call(user);
Output:
Hello, John
Here:
greet.call(user);
explicitly tells JavaScript to use user as this.
this With apply()
apply() works similarly to call().
The main difference is how arguments are passed.
function greet(message) {
console.log(`${message}, ${this.name}`);
}
const user = {
name: "John"
};
greet.apply(user, ["Hello"]);
Output:
Hello, John
The first argument specifies this.
The second argument is an array containing the function arguments.
this With bind()
The bind() method creates a new function with a permanently specified this value.
For example:
function greet() {
console.log(`Hello, ${this.name}`);
}
const user = {
name: "John"
};
const boundGreet = greet.bind(user);
boundGreet();
Output:
Hello, John
Here:
greet.bind(user)
creates a new function where this is bound to user.
call() vs apply() vs bind()
| Method | What it does |
|---|---|
call() | Calls the function immediately |
apply() | Calls the function immediately with arguments as an array |
bind() | Returns a new function with bound this |
For example:
greet.call(user);
greet.apply(user);
const newGreet = greet.bind(user);
this in JavaScript Event Handlers
this can behave differently in event handlers depending on how the handler is defined.
Consider:
button.addEventListener("click", function () {
console.log(this);
});
For a traditional event listener function, this generally refers to the element on which the listener is registered.
So if the listener is attached to a button:
this
refers to that button element.
For example:
button.addEventListener("click", function () {
console.log(this.textContent);
});
This can print the text of the clicked button.
Arrow Function Event Handler
Now consider:
button.addEventListener("click", () => {
console.log(this);
});
The arrow function doesn’t create its own this.
It inherits this from its surrounding scope.
If you need the event target, use the event object instead:
button.addEventListener("click", (event) => {
console.log(event.currentTarget);
});
This is often clearer and less confusing.
this in JavaScript Callbacks
Callbacks are another common place where developers encounter this problems.
For example:
const user = {
name: "John",
greet() {
setTimeout(function () {
console.log(this.name);
}, 1000);
}
};
user.greet();
The regular callback function has its own this behavior.
A common solution is an arrow function:
const user = {
name: "John",
greet() {
setTimeout(() => {
console.log(this.name);
}, 1000);
}
};
user.greet();
Output:
John
The arrow function inherits this from greet().
this in JavaScript Strict Mode
Strict mode changes the behavior of this in standalone regular functions.
Example:
"use strict";
function test() {
console.log(this);
}
test();
Output:
undefined
Without strict mode in a traditional browser script, a standalone function call can have the global object as this.
Modern JavaScript development commonly uses modules, classes, and strict-mode semantics, so understanding the execution context is important.
this in JavaScript Modules
JavaScript modules behave differently from traditional scripts.
For example:
console.log(this);
At the top level of an ES module, this is:
undefined
This is different from a traditional browser script where top-level this can refer to window.
Modern applications using tools such as React, Next.js, Node.js, and Vite commonly rely heavily on modules.
Common Mistakes With the this Keyword
Mistake 1: Assuming this Always Means the Current Object
A common misconception is:
“
thisalways refers to the object where the function is defined.”
That’s not generally true.
For regular functions, the call style matters.
Mistake 2: Using Arrow Functions as Object Methods Without Understanding this
Consider:
const user = {
name: "John",
greet: () => {
console.log(this.name);
}
};
This does not give the arrow function its own object-method this.
If you need the object as this, use a regular method:
const user = {
name: "John",
greet() {
console.log(this.name);
}
};
Mistake 3: Losing this When Passing a Method as a Callback
For example:
const user = {
name: "John",
greet() {
console.log(this.name);
}
};
const greet = user.greet;
greet();
The function has been detached from the object.
You can use bind() when you need to preserve the context:
const greet = user.greet.bind(user);
greet();
A Simple Way to Remember JavaScript this
When dealing with a regular function, start by asking:
How was this function called?
For example:
user.greet();
Here, the method is called through user.
With:
greet();
the function is called independently.
With:
greet.call(user);
this is explicitly set to user.
With:
new User();
this refers to the newly created object.
For arrow functions, remember:
Arrow functions inherit
thisfrom their surrounding lexical scope.
JavaScript this Keyword Cheat Sheet
| Situation | Value of this |
|---|---|
Object method obj.method() | The object used to call the method |
| Standalone regular function in strict mode | undefined |
call(obj) | Explicitly provided object |
apply(obj) | Explicitly provided object |
bind(obj) | Bound object |
Constructor with new | Newly created instance |
| Class constructor | New instance |
| Arrow function | Inherited lexical this |
| Traditional DOM event handler | The element receiving the handler |
| ES module top-level | undefined |
Best Practices for Using this in JavaScript
Understand the Call Site
When using a regular function, look at how the function is called before determining this.
Prefer Arrow Functions for Lexical Context
Arrow functions are useful for callbacks when you want to preserve the surrounding this.
Use Regular Methods for Object this
If a method needs to access properties through this, define it as a regular method.
Use bind() When Passing Methods Around
If a method needs to retain its original object context, bind() can make the behavior explicit.
Don’t Memorize Every Rule Blindly
Instead, understand the difference between:
Regular function → dynamic this
Arrow function → lexical this
Then examine the call site.
Why Is the JavaScript this Keyword Important?
The this keyword appears throughout JavaScript applications.
You’ll encounter it when working with:
- Objects
- Classes
- Constructor functions
- DOM events
- Callbacks
- JavaScript frameworks
- Libraries
- Function methods
call()apply()bind()
Understanding this makes it easier to understand existing JavaScript code and avoid common bugs.
It is particularly important when working with object-oriented JavaScript and codebases that use methods extensively.
Conclusion
The JavaScript this keyword can seem confusing because its behavior depends on the context in which it is used.
The most important distinction is between regular functions and arrow functions.
For regular functions, the value of this is generally determined by how the function is called.
For arrow functions, this is inherited from the surrounding lexical scope.
You should also understand how this behaves with objects, classes, constructors, event handlers, callbacks, call(), apply(), and bind().
The most useful rule to remember is:
For regular functions, look at the call site. For arrow functions, look at the surrounding scope.
Once you understand this distinction, one of JavaScript’s most confusing concepts becomes much easier to work with.
Frequently Asked Questions About the JavaScript this Keyword
What is this in JavaScript?
this is a special keyword whose value depends on the execution context. In regular functions, its value is generally determined by how the function is called.
What does this refer to in an object method?
When an object method is called as object.method(), this generally refers to the object used to call the method.
Do arrow functions have their own this?
No. Arrow functions don’t create their own this. They inherit it from their surrounding lexical scope.
What is the difference between this in regular functions and arrow functions?
Regular functions have a dynamically determined this based on how they are called. Arrow functions inherit this from the surrounding scope.
What do call(), apply(), and bind() do?
They allow developers to control the this value of regular functions. call() and apply() invoke the function immediately, while bind() creates a new function with a bound this.
Why does this become undefined in JavaScript?
In strict mode, a standalone regular function call has this set to undefined. Other contexts can also produce undefined depending on how the function is called.
Why is the JavaScript this keyword difficult?
Unlike some languages where this consistently refers to the current instance, JavaScript determines this differently depending on the function type and execution context.




