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

If you've ever written JavaScript and seen `this` behave in a way that made no sense, you're not alone. `this`, along with `call()`, `apply()`, and `bind()`, is one of those topics that trips up beginners (and sometimes experienced devs). This post breaks it down from the ground up—with real examples and the mistakes we all make—so you can use them confidently.

## **What is** `this`**?**

In simple terms, `this` **is a reference to the "owner" of the code that is currently running.**

It’s not always "the function itself" or "the file." It changes depending on **how** and **where** the function is called. That’s why it feels unpredictable at first.

### **Rule of thumb**

\- **Who called this function?** → Often, that’s what `this` refers to.

\- **In which context is the code running?** → That context often defines `this`.

We’ll make this precise with the rules below.

## **How JavaScript Decides What** `this` **Is**

JavaScript follows a few clear rules. Once you know them, `this` becomes predictable.

### **1\. Default binding (standalone function call)**

When you call a function **by itself** (not as a method on an object), `this` usually refers to the **global object**:

\- In a browser: `window`

\- In Node.js: `global` (or `globalThis` in modern JS)

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

sayHello(); // In browser: Window {...}  |  In Node: global object
```

**Common beginner mistake:** Assuming `this` is always the function or the script. In strict mode `'use strict'`), `this` in such calls is `undefined`, which can cause errors if you don’t expect it

### **2\. Implicit binding (method call)**

When you call a function **as a method** on an object (e.g. `obj.method()`), `this` is that **object**.

```javascript
const user = {
  name: 'Priya',
  greet() {
    console.log(`Hello, ${this.name}!`);
  }
};

user.greet(); // "Hello, Priya!"  →  this = user
```

So: **who called it?** → `user`. So **\***`this` **\=** `user`**\*\***.

**Common beginner mistake:** Storing the method in a variable and then calling it. That "loses" the object, so `this` is no longer `user`:

```javascript
onst greet = user.greet;
greet(); // "Hello, undefined!" (or error in strict mode)
// this is no longer user—it's window/global or undefined
```

### **3\. Explicit binding** `call`**,** `apply`**,** `bind`**)**

When you **explicitly** tell JavaScript: "when this function runs, set `this` to this value," you’re using **explicit binding**. That’s exactly what `call()`, `apply()`, and `bind()` do.

### **4.** `new` **binding (constructor)**

When you call a function with `new`, `this` is the **newly created object**:

```javascript
function Person(name) {
  this.name = name;
}

const p = new Person('Rahul');
console.log(p.name); // "Rahul"  →  this was the new object
```

## **Part 2:** `call()` **– Call a function with a chosen** `this`

**Syntax:**

```javascript
function.call(thisArg, arg1, arg2, ...)
```

\- **First argument:** what `this` should be inside the function.

\- **Rest of the arguments:** passed to the function as normal parameters.

**Example:**

```javascript
function introduce(greeting, punctuation) {
  console.log(`${greeting}, I'm ${this.name}${punctuation}`);
}

const person = { name: 'Sneha' };

introduce.call(person, 'Hi', '!');
// "Hi, I'm Sneha!"
// this = person, greeting = 'Hi', punctuation = '!'
```

**When to use** `call()`**:**

\- When you want to run a function **once** with a specific `this` and known arguments.

\- When borrowing a method from another object.

\- When you need to pass arguments one by one.

## **Part 3:** `apply()` **– Same idea, arguments as an array**

**Syntax:**

```javascript
function.apply(thisArg, [arg1, arg2, ...])
```

\- **First argument:** what `this` should be (same as `call`).

\- **Second argument:** **one array** of all the arguments for the function.

**Example:**

```javascript
introduce.apply(person, ['Hello', '.']);
// "Hello, I'm Sneha."
```

So:

\- `call(this, a, b, c)` → arguments listed one by one.

\- `apply(this, [a, b, c])` → arguments in a single array.

**When to use** `apply()`**:**

\- When your arguments are **already in an array** (e.g. from another function or API).

\- Historically used for things like `Math.max.apply(null, array)`. In modern JS you’d often use spread: `Math.max(...array)`.

If you have an array and want to use `call`, you can do:

```javascript
fn.call(thisArg, ...array)` — that’s like `apply(thisArg, array)
```

## **Part 4:** `bind()` **– Get a new function with** `this` **(and optional args) fixed**

**Syntax:**

```javascript
function.bind(thisArg, arg1?, arg2?, ...)
```

\- **First argument:** what `this` will always be in the new function.

\- **Optional:** you can also fix the first few arguments (partial application).

\- **Returns:** a **new function**. It does **not** run the original function immediately.

**Example:**

```javascript
const introduceSneha = introduce.bind(person);
introduceSneha('Hey', '!!');
// "Hey, I'm Sneha!!"
// this is always person, no matter how you call introduceSneha
```

Fixing both `this` and some arguments:

```javascript
const sayHiSneha = introduce.bind(person, 'Hi');
sayHiSneha('!');  // "Hi, I'm Sneha!"
```

**When to use** `bind()`**:**

\- When you need to **pass a callback** that must keep a specific `this` (e.g. event handlers, `setTimeout`, React class methods).

\- When you want a function that always runs with a fixed `this` (and optionally fixed arguments).

**Common beginner mistake:** Calling `bind()` and expecting the original function to run. It doesn’t—it only returns a new function. You still have to call that returned function.

```javascript
introduce.bind(person, 'Hi', '!');   // Does nothing visible—returns a function
introduce.bind(person, 'Hi', '!')(); // Correct: call the returned function
```

## **Quick comparison**

```javascript
| Method    | When it runs     | Arguments form   | Returns        |
|----------|------------------|------------------|----------------|
| `call()` | Immediately      | List: (a, b, c)  | Function result |
| `apply()`| Immediately      | Array: [a, b, c] | Function result |
| `bind()` | Not immediately  | List (optional)  | New function   |
```

## **Part 5: Fixing real-world mistakes**

### **Mistake 1: Losing** `this` **in a callback**

```javascript
const counter = {
  count: 0,
  increment() {
    this.count++;
    console.log(this.count);
  }
};

setTimeout(counter.increment, 1000); // NaN or error — this is not counter!
```

**Fix with** `bind`**:**

```javascript
setTimeout(counter.increment.bind(counter), 1000); // 1 (after 1 second)
```

### **Mistake 2: Passing a method as a callback (e.g. in event listeners)**

```javascript
button.addEventListener('click', obj.handleClick); // this might be the button, not obj
```

If you need `this` inside `handleClick` to be `obj`:

```javascript
button.addEventListener('click', obj.handleClick.bind(obj));
```

### **Mistake 3: Assuming** `this` **in nested functions**

```javascript
const obj = {
  name: 'Dev',
  outer() {
    function inner() {
      console.log(this.name); // this is not obj!
    }
    inner();
  }
};
obj.outer(); // undefined or error
```

**Fix:** Capture `this` in a variable, or use an arrow function for `inner` (arrow functions don’t have their own `this`; they use the surrounding one):

```javascript
outer() {
  const self = this;
  function inner() {
    console.log(self.name);
  }
  inner();
}
// Or: inner = () => console.log(this.name);
```

## **Part 6: How this fits with arrow functions**

Arrow functions (**\*\*do not\*\*** have their own `this`). They use the `this` of the scope where they were **defined** (lexical `this`).

```javascript
const obj = {
  name: 'Arrow',
  regular: function() { console.log(this.name); },
  arrow: () => console.log(this.name)
};

obj.regular(); // "Arrow"
obj.arrow();   // undefined (or window.name) — arrow took this from outer scope
```

So:

\- **Normal functions:** `this` = who called them / what you pass via `callapplybind`.

\- **Arrow functions:** `this` = from the surrounding code; `callapplybind` don’t change their `this`.

Use arrow functions when you want to keep the surrounding `this` (e.g. in callbacks). Use regular functions when you need `this` to be the object or something you pass with `call apply bind`.

## **Summary**

\- `this` = the "owner" of the current execution, decided by how (and where) the function is called.

\- `call(thisArg, ...args)` = run function **now** with that `this` and those arguments.

\- `apply(thisArg, [args])` = same, but arguments in **one array**.

\- `bind(thisArg, ...args?)` = return a **new function** with that `this` (and optional fixed arguments); call it later.

Once you know these rules and the typical mistakes (callbacks, nested functions, passing methods), you can debug `this` issues quickly and use `call`, `apply`, and `bind` on purpose instead of by trial and error.

*If this helped you, consider sharing it with someone who’s still confused by* `this`*. Happy coding!*

*Happy learning !*
