Skip to main content

Command Palette

Search for a command to run...

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

Updated
8 min read
The Magic of this, call(), apply(), and bind() in JavaScript

Introduction:

In JavaScript, the this keyword refers to the current execution context, or the object that "owns" the running code or function. Its value is not determined by where the function is defined, but by how it is called.

Here's how this behaves in different scenarios:

  • Alone (Global Context): When used outside of any function or object, this refers to the global object. In a web browser, this is the window object, while in Node.js, it's the global object.

  • In an Object Method: When a function is called as a method of an object, this refers to the object itself, allowing access to its properties and methods.

    For example:

    const person = {
      name: "Alice",
      greet: function() {
        console.log(`Hello, my name is ${this.name}`);
      }
    };
    
    person.greet();
    

Output:

Hello, my name is Alice

=== Code Execution Successful ===
  • In a Regular Function: Inside a standalone function (not as a method), this typically refers to the global object in non-strict mode. In strict mode, this is undefined.

  • In a Constructor Function: When a function is used as a constructor with the new keyword, this refers to the newly created object instance being constructed.

    For example:

    function Car(make) {
      this.make = make; // 'this' refers to the new Car instance
    }
    const myCar = new Car("Toyota");
    
  • In an Event Handler: In HTML event handlers, this usually refers to the DOM element that triggered the event.

In Arrow Functions: Arrow functions do not have their own this binding. Instead, they inherit this from the enclosing lexical scope (the scope where they were defined). This makes their behavior more predictable for callbacks.

The value of this can also be explicitly controlled using the [call()](https://developer.mozilla.org), [apply()](https://developer.mozilla.org), and [bind()](https://developer.mozilla.org) methods

this inside normal functions:

Here's an example of normal functions calling directly:

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

show();

Output:

<ref *1> Object [global] {
  global: [Circular *1],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  queueMicrotask: [Function: queueMicrotask],
  structuredClone: [Function: structuredClone],
  atob: [Function: atob],
  btoa: [Function: btoa],
  performance: [Getter/Setter],
  fetch: [Function: fetch],
  navigator: [Getter],
  crypto: [Getter],
  alert: [Function: log],
  prompt: [Function (anonymous)]
}

=== Code Execution Successful ===

this inside objects:

For example:

const ranveer = {
  name: "Ranveer",
  profession: "Actor",
  introduce() {
    return `My name is \({this.name} and I am an \){this.profession}`;
  }
};

console.log(ranveer.introduce());

Output:

My name is Ranveer and I am an Actor

=== Code Execution Successful ===

What call() does:

The call() method in JavaScript invokes a function immediately, allowing you to explicitly define the this context (the owner object) and pass arguments individually. It is primarily used for function borrowing, enabling one object to use a method belonging to another, thus increasing code reusability.

Key Aspects of call():

  • Context Setting: You can specify which object this refers to within the function.

  • Argument Passing: Arguments are passed individually, separated by commas (e.g., func.call(context, arg1, arg2)).

Immediate Execution: The function runs immediately when call() is invoked.

For example:

const person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
};

const person1 = { firstName: "John", lastName: "Doe" };

console.log(person.fullName.call(person1, "Oslo", "Norway"));

Output:

John Doe,Oslo,Norway

=== Code Execution Successful ===

Comparison to Other Methods:

  • apply(): Similar to call(), but accepts arguments as an array instead of individually.

  • bind(): Returns a new function with a bound this context, rather than executing it immediately.

    Note: In Python, __call__ is a special method that allows an instance of a class to be called as a function.

What apply() does:

In JavaScript, apply() calls a function with a specified this value and arguments provided as a single array (or array-like object). It is used to borrow methods from other objects or invoke functions where arguments are dynamically generated or already in an array format.

Key Aspects of apply():

  • Syntax: func.apply(thisArg, [argsArray]).

  • this Context: The first argument (thisArg) defines the this value inside the function.

  • Arguments: The second argument is an array or array-like object, which apply() spreads into individual arguments for the function.

  • Difference from call(): While call() takes arguments separately (func.call(this, arg1, arg2)), apply() takes them as a single array (func.apply(this, [arg1, arg2])).

  • Use Cases:

    • Method Borrowing: Using a method from one object on a different object.

Handling Arrays: Passing arrays to functions that expect individual arguments, such as Math.max.apply(null, [1, 2, 3]).

For example:

const person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
};

const person1 = {
  firstName: "John",
  lastName: "Doe"
};

console.log(person.fullName.apply(person1, ["Oslo", "Norway"]));

Output:

John Doe,Oslo,Norway

=== Code Execution Successful ===

Note: In other contexts like R, apply() is used for row- or column-wise operations on data frames.

What bind() does:

The bind() method is used to bind a specific object to a function so that the this keyword inside that function always refers to that object. Unlike call() or apply(), the bind() method does not execute the function immediately. Instead, it returns a new function that can be executed later with the desired this context.

In JavaScript, the value of this depends on how a function is called. Sometimes when a function is passed as a callback, used inside events, or stored in another variable, the value of this can change unexpectedly. The bind() method solves this problem by permanently attaching a specific object as the this value for that function.

Another powerful feature of bind() is that it can pre-set arguments for a function. This means you can partially apply arguments in advance, and when the new function is called later, those preset arguments will automatically be included.

Because of this behavior, bind() is often used in situations such as:

  • When passing methods as callbacks

  • When working with event handlers

  • When ensuring a function keeps the correct object context

  • When performing partial function application

For example:

const person = {
  fullName: function(city, country) {
    return this.firstName + " " + this.lastName + "," + city + "," + country;
  }
};

const person1 = {
  firstName: "John",
  lastName: "Doe"
};

const result = person.fullName.bind(person1, "Oslo", "Norway");

console.log(result());

Output:

John Doe,Oslo,Norway

=== Code Execution Successful ===

Difference between call, apply, and bind:

Feature call() apply() bind()
Purpose Call a function with a specific this Call a function with a specific this Create a new function with fixed this
Executes immediately Yes, it executes immediately Yes, it executes immediately No, it does executes immediately
Arguments Passed individually Passed as an array Passed individually
Return value Returns result of function Returns result of function Returns a new function

Conclusion: The Magic of this, call(), apply(), and bind()

JavaScript is a little funny sometimes. The keyword this is like a confused person who keeps asking, “Who am I talking about right now?” The answer depends on who called the function. If an object calls the function, then this points to that object.

Now sometimes JavaScript forgets who it should be talking about. That’s when call(), apply(), and bind() come in like helpful friends who say, “Relax, we’ll tell you exactly who this should be!”

  • call() says: “Hey function, run right now and use THIS object!”

  • apply() says the same thing but adds: “Here are your arguments in a nice little array.”

  • bind() is a bit lazy. It says: “I won’t run the function now. I’ll just prepare a new function and remember who this should be.”

So in simple silly terms:

call()  - run now
apply() - run now (but with array arguments)
bind()  - run later

In the end, the magic of this is just about knowing which object the function is talking about, and call(), apply(), and bind() help us control that conversation.

Once you understand this magic, JavaScript stops acting weird and starts making a lot more sense.