JavaScriptFunctionsthisWeb Development

The Magic of this, call, apply, and bind in JavaScript

Piyush Kumar
4 min read
The Magic of this, call, apply, and bind in JavaScript

If you have ever been confused by this, you are not alone. The easiest way to understand it is simple: this points to who is calling the function. It is not fixed inside the function body. It changes based on the call site. In this article, we start with this, then move to call, apply, and bind with small examples you can try immediately.

What this Means in JavaScript

this is a keyword that refers to the object that calls a function. The same function can return different this values depending on how you call it.

Think of it like a speaker on a mic. The words are the same, but the person holding the mic changes.

this Inside Normal Functions

In a normal function, the value of this depends on how the function is called.

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

showCaller(); // In a browser, this is the window object in non strict mode

If you call a normal function without an object, this refers to the global object in non strict mode. In strict mode, it becomes undefined.

"use strict";
function showCallerStrict() {
  console.log(this);
}

showCallerStrict(); // undefined

this Inside Objects

When a function is called as a method of an object, this points to that object.

const user = {
  name: "Piyush",
  greet() {
    console.log(`Hello, I am ${this.name}`);
  },
};

user.greet(); // Hello, I am Piyush

Here, the object user is calling greet, so this is user.

If you copy the method and call it alone, the caller changes. This happens because this is decided at the time of the call, not when the function is written. The same function can behave differently based on the object in front of the dot.

const greetFn = user.greet;

greetFn(); // this is no longer user

In this case, there is no object before the dot, so the function is just a plain function call. In non strict mode, this becomes the global object. In strict mode, it becomes undefined. That is why this.name does not work here.

Another Simple Example

const car = {
  brand: "Honda",
  show() {
    console.log(this.brand);
  },
};

const showFn = car.show;
car.show();   // Honda
showFn();     // global or undefined

This is the most common source of confusion with this.

What call() Does

call() lets you call a function and set what this should be. It takes a list of arguments after the first parameter.

function greet(city) {
  console.log(`${this.name} from ${city}`);
}

const person = { name: "Aman" };

greet.call(person, "Delhi"); // Aman from Delhi

Use call() when you want to borrow a function and run it immediately with a different caller.

What apply() Does

apply() is almost the same as call(), but it takes arguments as an array.

function add(a, b) {
  return a + b;
}

const nums = [4, 6];
console.log(add.apply(null, nums)); // 10

This is helpful when your arguments already exist in an array.

What bind() Does

bind() does not call the function immediately. It returns a new function where this is fixed to a value.

function sayName() {
  console.log(this.name);
}

const person = { name: "Riya" };
const boundSayName = sayName.bind(person);

boundSayName(); // Riya

Use bind() when you want to pass a method around but keep the same caller.

Difference Between call, apply, and bind

  • call runs the function now and takes arguments one by one
  • apply runs the function now and takes arguments as an array
  • bind returns a new function that you can run later
MethodWhen it runsHow arguments are passedResult
callImmediatelyComma separatedFunction result
applyImmediatelyArrayFunction result
bindLaterComma separated or arrayNew function

Assignment Idea

Try this small exercise to make the concepts stick.

  1. Create an object with a method that uses this.
  2. Borrow that method using call().
  3. Use apply() with an array of arguments.
  4. Use bind() and store the new function, then call it.

Example

const profile = {
  name: "Neha",
  intro(role) {
    console.log(`${this.name} is a ${role}`);
  },
};

const other = { name: "Rahul" };

profile.intro.call(other, "Developer");
profile.intro.apply(other, ["Designer"]);

const boundIntro = profile.intro.bind(other);
boundIntro("Engineer");

Quick Recap

  • this means who is calling the function
  • Normal function calls depend on the call site
  • Object methods point this to the object
  • call and apply run immediately with a chosen caller
  • bind returns a new function with a fixed caller