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

## **Introduction**

Imagine you are in a chai shop in Delhi. The shop owner has a recipe for making chai. When you ask for chai, the owner makes it using their equipment and ingredients. The "chai shop owner" is the context, and "you" are the one requesting it. In JavaScript, `this` works the same way. It refers to the object that is calling the function.

In this blog, we will learn what `this` means, and three powerful methods (`call()`, `apply()`, and `bind()`) that let you control which object `this` refers to.

* * *

## **1\. What this Means in JavaScript (Simple Explanation)**

`this` **refers to the object that is calling the function.**

Think of `this` as an answer to the question: "Who is calling me?"

### **Simple Real-Life Analogy**

Imagine you are a teacher, and you say "I will teach my class today."

*   If you are teaching at School A, "I" means "the teacher at School A"
    
*   If you are teaching at School B, "I" means "the teacher at School B"
    

The same person (you), but the meaning of "I" changes based on the context. Similarly, `this` changes based on who is calling the function.

### **Simple Code Example**

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

person.greet(); // Output: Hello, my name is Ashish
```

In this example, `person` is calling the `greet` function. So `this` refers to `person`, and `this.name` is "Ashish".

### **Global Context**

When no object calls the function, `this` refers to the global object (in browsers, it is `window`):

```javascript
function sayName() {
  console.log(this);
}

sayName(); // this refers to global object (window in browsers)
```

* * *

## **2\. this Inside Normal Functions**

When a function is called directly (not as part of an object), `this` refers to the global object.

### **Example 1: Function Without an Object**

```javascript
function introduce() {
  console.log("My name is " + this.name);
}

introduce(); // this refers to global object, this.name is undefined
```

In strict mode, `this` would be `undefined`:

```javascript
"use strict";

function introduce() {
  console.log(this); // undefined in strict mode
}

introduce();
```

### **Example 2: Variable in Global Scope**

```javascript
let globalName = "World";

function greet() {
  console.log("Hello, " + this.name); // Tries to access global.name
}

greet(); // Output: Hello, undefined
```

The function cannot access variables directly through `this` in the global scope.

### **Key Point**

In normal functions, `this` is determined by **how the function is called**, not where it is defined.

```javascript
let person = {
  name: "Ashish"
};

function getName() {
  return this.name;
}

// Called as a normal function
console.log(getName()); // Output: undefined (this is global)

// Called through the person object
console.log(person.getName = getName); // We will assign it next
```

* * *

## **3\. this Inside Objects**

When a function is called as a method of an object (using dot notation), `this` refers to that object.

### **Example 1: Simple Object with Method**

JavaScript

```javascript
const student = {
  name: "Ashish",
  age: 20,
  greet: function() {
    console.log("Hello, I am " + this.name);
  }
};

student.greet(); // Output: Hello, I am Ashish
```

Here, `student` calls the `greet` function, so `this` refers to `student`.

### **Example 2: Accessing Multiple Properties**

JavaScript

```javascript
const college = {
  name: "IIIT Bangalore",
  founded: 2009,
  getInfo: function() {
    return this.name + " was founded in " + this.founded;
  }
};

console.log(college.getInfo());
// Output: IIIT Bangalore was founded in 2009
```

### **Example 3: Modifying Object Properties with this**

JavaScript

```javascript
const bank = {
  accountBalance: 10000,
  deposit: function(amount) {
    this.accountBalance += amount;
    console.log("New balance: " + this.accountBalance);
  },
  withdraw: function(amount) {
    this.accountBalance -= amount;
    console.log("New balance: " + this.accountBalance);
  }
};

bank.deposit(5000);   // Output: New balance: 15000
bank.withdraw(2000);  // Output: New balance: 13000
```

### **Important: this is Dynamic**

The value of `this` depends on how the function is called, not where it is defined:

```javascript
const person1 = {
  name: "Ashish",
  greet: function() {
    console.log("Hello, I am " + this.name);
  }
};

const person2 = {
  name: "Priya"
};

// Calling through person1
person1.greet(); // Output: Hello, I am Ashish

// Calling through person2
person2.greet = person1.greet;
person2.greet(); // Output: Hello, I am Priya (this refers to person2 now!)
```

Even though we are using the same function, `this` changes based on which object calls it!

* * *

## **4\. What call() Does**

The `call()` method lets you call a function and specify what `this` should refer to. It executes the function immediately.

### **Syntax**

```javascript
functionName.call(objectToUseAsThis, arg1, arg2, ...);
```

### **Example 1: Using call() to Set this**

```javascript
function introduce() {
  console.log("My name is " + this.name);
}

const ashish = { name: "Ashish" };
const priya = { name: "Priya" };

// Call the function with ashish as this
introduce.call(ashish); // Output: My name is Ashish

// Call the function with priya as this
introduce.call(priya);  // Output: My name is Priya
```

Without `call()`, we could not reuse this function for different objects. With `call()`, we can!

### **Example 2: call() with Arguments**

```javascript
function calculateAge(currentYear) {
  return currentYear - this.birthYear;
}

const ashish = { birthYear: 2005 };
const priya = { birthYear: 2004 };

let ashishAge = calculateAge.call(ashish, 2026); // Output: 21
let priyaAge = calculateAge.call(priya, 2026);   // Output: 22

console.log(ashishAge); // Output: 21
console.log(priyaAge);  // Output: 22
```

Arguments after the object are passed to the function.

### **Example 3: College Enrollment**

```javascript
function enrollStudent(semester, course) {
  console.log(this.name + " enrolled in " + course + " in semester " + semester);
}

const student1 = { name: "Ashish" };
const student2 = { name: "Priya" };

enrollStudent.call(student1, 4, "Data Structures");
// Output: Ashish enrolled in Data Structures in semester 4

enrollStudent.call(student2, 3, "Web Development");
// Output: Priya enrolled in Web Development in semester 3
```

### **Example 4: Borrowing Methods from Objects**

```javascript
const person = {
  name: "Ashish",
  greet: function(greeting) {
    console.log(greeting + ", " + this.name);
  }
};

const pet = {
  name: "Buddy"
};

// Borrow the greet method from person for pet
person.greet.call(pet, "Woof"); // Output: Woof, Buddy
```

Even though `pet` does not have a `greet` method, we can use the one from `person`!

* * *

## **5\. What apply() Does**

The `apply()` method is similar to `call()`, but instead of listing arguments one by one, you pass them as an array.

### **Syntax**

```javascript
functionName.apply(objectToUseAsThis, [arg1, arg2, ...]);
```

### **Example 1: Using apply()**

```javascript
function introduce(greeting, punctuation) {
  console.log(greeting + ", my name is " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// Using call (arguments one by one)
introduce.call(ashish, "Hello", "!");
// Output: Hello, my name is Ashish!

// Using apply (arguments in an array)
introduce.apply(ashish, ["Hello", "!"]);
// Output: Hello, my name is Ashish!
```

Both produce the same result. The difference is how you pass arguments.

### **Example 2: Finding Maximum with apply()**

A common use of `apply()` is to pass array elements as arguments:

```javascript
const numbers = [10, 20, 50, 30, 5];

// Math.max expects individual arguments, not an array
// Without apply, this would not work:
// console.log(Math.max(numbers)); // Output: NaN

// With apply, we convert the array to individual arguments:
let max = Math.max.apply(null, numbers);
console.log(max); // Output: 50
```

### **Example 3: Adding Multiple Numbers**

```javascript
function addNumbers(a, b, c, d) {
  return a + b + c + d;
}

const numbers = [10, 20, 30, 40];

let sum = addNumbers.apply(null, numbers);
console.log(sum); // Output: 100
```

### **Important: The First Argument (null or object)**

When the object does not matter (or there is no specific object to use), pass `null`:

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

let result = add.apply(null, [5, 10]); // null means "no specific object"
console.log(result); // Output: 15
```

* * *

## **6\. What bind() Does**

The `bind()` method creates a new function with a fixed `this` value. Unlike `call()` and `apply()`, `bind()` does NOT execute the function immediately. It returns a new function that you can call later.

### **Syntax**

```javascript
const newFunction = functionName.bind(objectToUseAsThis, arg1, arg2, ...);
```

### **Example 1: Using bind()**

```javascript
function greet(greeting) {
  console.log(greeting + ", " + this.name);
}

const ashish = { name: "Ashish" };

// Create a new function with ashish as this
const ashishGreet = greet.bind(ashish);

// Call it later
ashishGreet("Hello"); // Output: Hello, Ashish
ashishGreet("Hi");    // Output: Hi, Ashish
```

Notice that we create the function first with `bind()`, then call it later. This is different from `call()` and `apply()`, which execute immediately.

### **Example 2: bind() with Preset Arguments**

You can also preset some arguments:

```javascript
function calculateFee(baseFee, discountPercentage) {
  let discount = baseFee * (discountPercentage / 100);
  return baseFee - discount;
}

const student = { name: "Ashish" };

// Create a function with preset discount of 10%
const calculateStudentFee = calculateFee.bind(null, 50000, 10);

let fee = calculateStudentFee();
console.log(fee); // Output: 45000
```

### **Example 3: bind() in Event Handlers**

A common use of `bind()` is in event handlers:

```javascript
const person = {
  name: "Ashish",
  clickHandler: function() {
    console.log("Button clicked by " + this.name);
  }
};

// Without bind, this would refer to the button element
// With bind, this refers to person
const button = document.querySelector("button");
button.addEventListener("click", person.clickHandler.bind(person));
```

(This is more advanced, but shows a real-world use case.)

### **Example 4: bind() for Later Execution**

JavaScript

```javascript
function greetStudent(greeting, subject) {
  console.log(greeting + " " + this.name + ", you are learning " + subject);
}

const ashish = { name: "Ashish" };
const priya = { name: "Priya" };

// Create bound functions
const greetAshish = greetStudent.bind(ashish);
const greetPriya = greetStudent.bind(priya);

// Use them later
greetAshish("Welcome", "JavaScript");  // Output: Welcome Ashish, you are learning JavaScript
greetPriya("Hi", "Python");            // Output: Hi Priya, you are learning Python
```

* * *

## **7\. Difference Between call(), apply(), and bind()**

Now let's compare these three powerful methods.

### **Quick Comparison**

| **Method** | **Executes Immediately** | **Arguments** | **Returns** |
| --- | --- | --- | --- |
| **call()** | Yes | One by one: `arg1, arg2` | Function result |
| **apply()** | Yes | As array: `[arg1, arg2]` | Function result |
| **bind()** | No | One by one: `arg1, arg2` | New function (not executed) |

### **Side-by-Side Examples**

#### **call() Example**

```javascript
function introduce(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// call executes immediately with arguments one by one
introduce.call(ashish, "Hello", "!");
// Output: Hello, Ashish! (executed immediately)
```

#### **apply() Example**

```javascript
function introduce(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// apply executes immediately with arguments as array
introduce.apply(ashish, ["Hello", "!"]);
// Output: Hello, Ashish! (executed immediately)
```

#### **bind() Example**

```javascript
function introduce(greeting, punctuation) {
  console.log(greeting + ", " + this.name + punctuation);
}

const ashish = { name: "Ashish" };

// bind creates a new function (not executed yet)
const ashishIntroduce = introduce.bind(ashish, "Hello", "!");

// Call it later
ashishIntroduce();
// Output: Hello, Ashish! (executed when we call it)
```

### **When to Use Each**

#### **Use call() When**

You want to execute a function immediately with a specific `this` and arguments one by one:

```javascript
function sayHello(greeting) {
  console.log(greeting + ", " + this.name);
}

const person = { name: "Ashish" };

sayHello.call(person, "Hello"); // Execute now
```

#### **Use apply() When**

You want to execute a function immediately with a specific `this` but have arguments in an array:

```javascript
function sum(a, b, c) {
  return a + b + c;
}

const numbers = [10, 20, 30];
let result = sum.apply(null, numbers); // Execute now with array
```

#### **Use bind() When**

You want to create a new function to use later:

```javascript
function calculateAge(year) {
  return 2026 - this.birthYear - year;
}

const person = { birthYear: 2005 };

// Create for later use
const getPersonAge = calculateAge.bind(person, 5);

// Use it later
console.log(getPersonAge()); // Output: 16
```

### **Detailed Comparison Table**

| **Aspect** | **call()** | **apply()** | **bind()** |
| --- | --- | --- | --- |
| **Executes immediately** | Yes | Yes | No |
| **Returns** | Function result | Function result | New function |
| **Arguments format** | One by one: `arg1, arg2` | Array: `[arg1, arg2]` | One by one: `arg1, arg2` |
| **First parameter** | Object for `this` | Object for `this` | Object for `this` |
| **Use case** | Quick execution | Array arguments | Store for later |
| **Example** | `fn.call(obj, 1, 2)` | `fn.apply(obj, [1, 2])` | `fn.bind(obj, 1, 2)` |

* * *

## **Visual Representation**

### **How call() Works**

```plaintext
Function Definition
        |
        v
    sayHi()
        |
        +------ call(person1) ------> Execute with person1 as this
        |
        +------ call(person2) ------> Execute with person2 as this
        
Result: Function executes immediately with specified this
```

### **How apply() Works**

```plaintext
Function Definition
        |
        v
    addNumbers()
        |
        +------ apply(null, [10, 20]) ------> Execute with array as arguments
        
Result: Function executes immediately, array unpacked to arguments
```

### **How bind() Works**

```plaintext
Function Definition
        |
        v
    greet()
        |
        +------ bind(ashish, "Hello") ------> Create NEW function
        |
        v
   boundGreet
        |
        +------ Call later when needed ------> Execute
        
Result: New function created, not executed until called
```

* * *

## **Summary**

1.  `this` **refers to the object that is calling the function**
    
    *   In normal functions, `this` is the global object
        
    *   In object methods, `this` refers to that object
        
2.  `call()` **executes a function immediately with a specific** `this` **and arguments one by one**
    
    *   Syntax: `fn.call(object, arg1, arg2)`
        
    *   Use when you need immediate execution
        
3.  `apply()` **executes a function immediately with a specific** `this` **and arguments as an array**
    
    *   Syntax: `fn.apply(object, [arg1, arg2])`
        
    *   Use when arguments are in an array
        
4.  `bind()` **creates a new function with a fixed** `this` **value for later use**
    
    *   Syntax: `fn.bind(object, arg1, arg2)`
        
    *   Use when you need to store a function for later
        
5.  **Key differences**:
    
    *   `call()` and `apply()` execute immediately
        
    *   `bind()` creates a new function
        
    *   `call()` and `bind()` use arguments one by one
        
    *   `apply()` uses arguments as an array
        
6.  **Real-world uses**:
    
    *   Borrowing methods from other objects
        
    *   Creating specialized versions of functions
        
    *   Using in event handlers and callbacks
        
    *   Working with array methods like `Math.max()`
