Skip to main content

Command Palette

Search for a command to run...

Understanding `this`, call(), apply(), and bind() in JavaScript

Who's calling the function? A beginner-friendly guide to JavaScript's most confusing keyword

Updated
•7 min read•View as Markdown
Understanding `this`, call(), apply(), and bind() in JavaScript
S
I'm a passionate software engineer and full-stack MERN developer who loves to turn ideas into scalable, user-centric applications. I have hands-on experience in building modern web solutions using React, Node.js, Express.js, MongoDB, following clean architecture and best development practices. My experience in the Cognizant Healthcare Product Consulting (HPC) program has given me hands-on exposure to SQL, PL/SQL, U.S. healthcare payer systems and TriZetto Facets, and has helped me to further develop my skills in working with enterprise software in domain-driven environments. I enjoy tackling complex technical problems, constantly learning, and building reliable applications that deliver business value.

If you've been following along in this series, you already know how functions, arrays, and objects work in JavaScript. Today we're tackling something that trips up almost every beginner (and honestly, a few experienced devs too): the keyword this.

By the end of this article, you'll understand this, and you'll also know how to control it using three handy methods: call(), apply(), and bind().


1. What Does this Mean in JavaScript? (Simple Explanation)

Here's the simplest way to think about this:

this means "who is calling the function."

That's it. this isn't about where a function is written - it's about who calls it.

Think of it like a phone call. If your mom calls you, you say "Hi Mom." If your friend calls you, you say "Hi [friend's name]." You (the function) haven't changed - but how you respond depends on who's on the other end of the call.

function greet() {
  console.log("Hello, " + this.name);
}

Right now, this function doesn't know who this is. It depends entirely on how greet() gets called. Let's see that in action.


2. this Inside Normal Functions

When you call a normal function on its own (not attached to any object), this doesn't point to anything useful for beginners - it points to the global object (or undefined in strict mode).

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

whoIsThis();

// Output: behaviour of this in different environment

// In a browser: logs the "window" object
// In strict mode: logs "undefined"

Why? Because nobody meaningful is "calling" this function - it's just being called directly, with no object in front of it.

function sayHi() {
  console.log("Hi, I am " + this.name);
}

sayHi(); // "Hi, I am undefined"

// because `this` isn't pointing to any object with a "name"

At this stage, just remember: a plain function call has no clear "caller," so this isn't useful yet. That changes as soon as we attach the function to an object.


3. this Inside Objects

This is where this starts to make sense. When a function is a method (a function stored inside an object) and you call it through that object, this refers to the object doing the calling.

const user = {
  name: "Sahil",
  greet: function () {
    console.log("Hello, I am " + this.name);
  }
};

user.greet(); // "Hello, I am Sahil"

Here's the key moment: user.greet() - the object user is standing right before the dot when we call the function. That makes user the "caller," so this becomes user.

Before / After: Same Function, Different Caller

const student = {
  name: "Riya",
  greet: function () {
    console.log("Hi, I'm " + this.name);
  }
};

const teacher = {
  name: "Meera",
  greet: student.greet // borrowing the same function!
};

student.greet(); // "Hi, I'm Riya"
teacher.greet(); // "Hi, I'm Meera"

Same function. Same code. Two different outputs - because the caller changed. This is the whole idea of this in one example.


4. What Does call() Do?

call() lets you run a function and manually decide what this should be - even if the function doesn't naturally belong to that object.

function greet() {
  console.log("Hello, I am " + this.name);
}

const person = { name: "Aman" };

greet.call(person); // "Hello, I am Aman"

Here, greet was never attached to person. But call() says: "Run greet(), and pretend person is the one calling it."

You can also pass arguments after the object, one by one:

function introduce(city, hobby) {
  console.log(`I am ${this.name} from ${city}. I love ${hobby}.`);
}

const person = { name: "Aman" };

introduce.call(person, "Mumbai", "cricket"); // "I am Aman from Mumbai. I love cricket."

5. What Does apply() Do?

apply() does the exact same job as call() - the only difference is how you pass arguments. Instead of listing them one by one, you pass them as an array.

function introduce(city, hobby) {
  console.log(`I am ${this.name} from ${city}. I love ${hobby}.`);
}

const person = { name: "Aman" };

introduce.apply(person, ["Mumbai", "cricket"]); // "I am Aman from Mumbai. I love cricket."

Notice: same result as call(), but the arguments ["Mumbai", "cricket"] are packed into one array instead of being written separately.

Handy real-world use: apply() is great when you already have your data sitting in an array and don't want to unpack it manually.


6. What Does bind() Do?

call() and apply() run the function immediately. bind() is different - it doesn't run the function right away. Instead, it gives you back a new function, permanently linked to the this you chose, which you can call whenever you want.

function greet() {
  console.log("Hello, I am " + this.name);
}

const person = { name: "Aman" };

const boundGreet = greet.bind(person);

boundGreet(); // "Hello, I am Aman" — runs whenever YOU decide to call it

Think of bind() as pre-setting the caller and saving the function for later - like saving a contact in your phone so you don't have to dial the number every time.

function introduce(city) {
  console.log(`I am ${this.name} from ${city}.`);
}

const person = { name: "Aman" };
const introduceAman = introduce.bind(person, "Mumbai");

introduceAman(); // "I am Aman from Mumbai."

7. Difference Between call, apply, and bind

Feature call() apply() bind()
Runs the function immediately? Yes Yes No - returns a new function
How arguments are passed One by one As an array One by one (can be partial)
Returns The function's result The function's result A new function
Best used when You have a few known arguments Your arguments are already in an array You want to use the function later

Quick Way to Remember

  • call - comma-separated arguments

  • apply - array of arguments

  • bind - be used later (doesn't run immediately)


Diagram: Function → Caller Relationship

The pattern is always the same: find who's standing before the function when it's called - that's this.


Assignment: Practice this, call(), apply(), and bind()

Try this on your own before checking the solution:

  1. Create an object student with a name and a method introduce that uses this.name.

  2. Create a plain object otherStudent (just a name, no method).

  3. Borrow student.introduce and run it on otherStudent using call().

  4. Run the same method on otherStudent using apply(), passing arguments as an array.

  5. Use bind() to create a new function tied to otherStudent, store it in a variable, and call it separately.

Click to see the solution
const student = {
  name: "Sahil",
  introduce: function (city, hobby) {
    console.log(`I am ${this.name} from ${city}. I love ${hobby}.`);
  }
};

const otherStudent = { name: "Priya" };

// Using call()
student.introduce.call(otherStudent, "Delhi", "reading"); // "I am Priya from Delhi. I love reading."


// Using apply()
student.introduce.apply(otherStudent, ["Delhi", "reading"]); // "I am Priya from Delhi. I love reading."


// Using bind()
const introducePriya = student.introduce.bind(otherStudent, "Delhi", "reading");
introducePriya(); // "I am Priya from Delhi. I love reading."

Wrapping Up

this isn't magic - it's just a question: "Who called this function?" Once you start asking that question every time you see this in code, it stops being confusing.

  • Plain function call - this isn't useful (global or undefined)

  • Called through an object - this is that object

  • call() / apply() - you choose this and run immediately

  • bind() - you choose this and save it for later


If you found this useful, drop a comment or a reaction.

More from this blog

Sahil Gupta | Web Development, Frontend, Backend & DevOps

53 posts

I'm a passionate software engineer and full-stack MERN developer who loves to turn ideas into scalable, user-centric applications. I have hands-on experience in building modern web solutions using React, Node.js, Express.js, MongoDB, following clean architecture and best development practices. My experience in the Cognizant Healthcare Product Consulting (HPC) program has given me hands-on exposure to SQL, PL/SQL, U.S. healthcare payer systems and TriZetto Facets, and has helped me to further dev