Understanding this, bind, call, and apply in JavaScript

In JavaScript, this
is a reference to an object. What this
refers to can change depending on the context in which a function is called. Sometimes it’s decided implicitly by how the function is called, and sometimes you can set it explicitly using bind
, call
, and apply
.
Even though this
might seem confusing at first, it's something you'll run into early when writing JavaScript—whether you're working with the DOM, using object methods, building classes, or writing regular functions.
In this blog, we’ll explore how this
behaves in different situations and how you can control it using bind
, call
, and apply
.
Implicit Context
There are four main situations where this
is decided based on how the function is called:
In the global context
Inside a method of an object
Inside a constructor function or class
In a DOM event handler
Global Context
When you're in the global context (not inside any object or function), this
refers to the global object. In a browser, that's window
. In Node.js, it's global
.
console.log(this);
// In browser: Window {...}
// In Node.js: global {...}
Functions create their own scope for variables (their own Execution context), but this
doesn't follow the same rule. In a top-level function, this
still refers to the global object, not the function's local scope.
function printThis() {
console.log(this);
}
printThis();
// In browser: Window {...}
However, if you use strict mode, this
inside a regular function becomes undefined
:
'use strict';
function printThis() {
console.log(this);
}
printThis();
// undefined
Generally, it is safer to use strict mode to reduce the probability of this
having an unexpected scope.
As a Method in an Object
When you call a function as a method of an object, this
refers to that object:
const country = {
name: 'USA',
yearFounded: 1776,
describe() {
console.log(`${this.name} was founded in ${this.yearFounded}.`);
},
};
country.describe();
// "USA was founded in 1776."
In a nested object, this
still refers to the immediate object the method belongs to:
const country = {
details: {
symbol: 'eagle',
currency: 'USD',
printDetails() {
console.log(`Symbol: ${this.symbol}, Currency: ${this.currency}`);
},
},
};
country.details.printDetails();
// "Symbol: eagle, Currency: USD"
this
usually refers to the object on the left side of the dot when the function is called.
Constructor Function
When using new
to create an object from a constructor function, this
refers to the newly created object:
function Country(name, year) {
this.name = name;
this.yearFounded = year;
this.describe = function () {
console.log(`${this.name} was founded in ${this.yearFounded}.`);
};
}
const usa = new Country('USA', 1776);
usa.describe();
// "USA was founded in 1776."
Class Constructor
Using the class
syntax works the same way for this
:
class Country {
constructor(name, year) {
this.name = name;
this.yearFounded = year;
}
describe() {
console.log(`${this.name} was founded in ${this.yearFounded}.`);
}
}
const usa = new Country('USA', 1776);
usa.describe();
// "USA was founded in 1776."
DOM Event Handler
In an event listener, this
usually refers to the element that received the event. In other words, In an event handler, this
refers to the element the listener is attached to (same as event.currentTarget
). Instead of using this
developers often use event.target
or event.currentTarget
to access the element directly.
const button = document.createElement('button');
button.textContent = 'Click me';
document.body.append(button);
button.addEventListener('click', function () {
console.log(this); // refers to the button element
});
Output:
<button>Click me</button>
Explicit Context with call
, apply
, and bind
Sometimes, you need to manually set what this
refers to. That’s where call
, apply
, and bind
come in.
All these methods are used for method/functions borrowing/sharing.
call()
and apply()
In this example, we’ll create an object, and create a function that references this
but has no this
context.
const book = {
title: 'Brave New World',
author: 'Aldous Huxley',
}
function summary() {
console.log(`${this.title} was written by ${this.author}.`)
}
summary()
Output:
"undefined was written by undefined"
Since summary
and book
have no connection, invoking summary
by itself will only print undefined
, as it’s looking for those properties on the global object.
💡 Note: In strict mode,
this
isundefined
, so trying to accessthis.title
will throw:Uncaught TypeError: Cannot read property 'title' of undefined
.
However, you can use call
and apply
to invoke the this
context of book
on the function.
Both call
and apply
invoke a function immediately and allow you to pass a value for this
:
const book = {
title: 'Brave New World',
author: 'Aldous Huxley',
};
function summary() {
console.log(`${this.title} was written by ${this.author}.`);
}
summary.call(book);
summary.apply(book);
// "Brave New World was written by Aldous Huxley."
There is now a connection between book
and summary
when these methods are applied.
They differ in how arguments are passed:
call
accepts arguments one-by-one:
function details(genre, year) {
console.log(`${this.title} is a ${genre} novel written in ${year}.`);
}
details.call(book, 'dystopian', 1932);
// "Brave New World is a dystopian novel written in 1932."
apply
takes arguments as an array:
details.apply(book, ['dystopian', 1932]);
// Brave New World is a dystopian novel written in 1932
bind()
Unlike call
and apply
, bind
does not execute the function immediately. Instead, it returns a new function with the this
value permanently set.
bind
can be particularly helpful when you want to use events to access properties of one class within another class. For example, if you were to write a simple game, you might separate the user interface and I/O into one class, and the game logic and state into another. Since the game logic would need to access input, such as key press and click, you would want to bind
the events to access the this
value of the game logic class.
const getSummary = summary.bind(book);
getSummary(); // "Brave New World was written by Aldous Huxley."
Once a function is bound, you can't rebind it:
const book2 = {
title: '1984',
author: 'George Orwell',
};
getSummary.bind(book2);
getSummary(); // Still prints for Brave New World
Arrow Functions and this
Arrow functions behave differently—they don’t have their own this
. Instead, they inherit this
from their surrounding context.
const person = {
name: 'Leslie',
regularFunc: function () {
console.log(this.name);
},
arrowFunc: () => {
console.log(this.name);
},
};
person.regularFunc(); // 'Leslie'
person.arrowFunc(); // undefined (inherits from outer scope)
arrowFunc
is defined inside the object literal, not inside a method or class.So its
this
comes from the outer (global) context — not from theperson
object.In the global scope (in browsers),
this
is usuallywindow
, andwindow.name
is usually""
orundefined
unless explicitly set.
This is especially useful when dealing with callbacks and event listeners in classes:
const button = document.createElement('button');
button.textContent = 'Click me';
document.body.append(button);
class Display {
constructor() {
this.text = 'Updated text';
button.addEventListener('click', event => {
event.target.textContent = this.text;
});
}
}
new Display();
If you click the button, the text content will change to the value of buttonText
. If you hadn’t used an arrow function here, this
would be equal to event.currentTarget
(as seen in DOM event handler), and you wouldn’t be able to use it to access a value within the class without explicitly binding it.
Key Differences: call
, apply
, and bind
Method | Executes Function Immediately? | Argument Format | Returns | Use Case |
call | Yes | Comma-separated values | Function result | Call a function with a specific this and arguments |
apply | Yes | Arguments as an array | Function result | Same as call , useful when arguments are in an array |
bind | No | Comma-separated values | New function | Create a new function with this permanently bound |
When to Use What
Use
call
when you want to invoke a function immediately with a customthis
and a list of arguments.func.call(obj, arg1, arg2);
Use
apply
when arguments are already in an array and you want to call the function immediately.func.apply(obj, [arg1, arg2]);
Use
bind
when you want to create a new function withthis
bound to a specific object but invoke it later.const newFunc = func.bind(obj); newFunc(arg1, arg2);
Thanks for reading! I hope this post helped you understand how this
, call
, apply
, and bind
work in JavaScript. If you found it helpful, feel free to share it with others or drop your thoughts in the comments. Happy coding! 🚀
Subscribe to my newsletter
Read articles from Deepthi Purijala directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Deepthi Purijala
Deepthi Purijala
Full Stack Developer with hands-on experience of more than 1 year. Proficient in both Back-end and Front-end technologies, with a strong commitment to delivering high-quality code