# Understanding this in JavaScript

## Introduction

Most JavaScript confusion around `this` comes from one wrong assumption: that `this` depends on where a function is defined. It doesn't. It depends on who called the function.

That one shift in thinking makes most of the confusion go away.

* * *

## What `this` Actually is

`this` is a reference to the calling context of a function. When a function runs, JavaScript looks at what triggered the call and sets `this` to that thing.

Not where the function lives in your file. Not which object it belongs to in your source code. Who called it at runtime.

* * *

## `this` in the Global Context

When you call a plain function with nothing owning it, `this` falls back to the global object.

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

greet();
```

In a browser, that logs `window`. In Node.js, it's `global`. In strict mode, it's `undefined`.

Nobody specific called it, so JavaScript picks the default.

* * *

## `this` Inside an Object

This is where `this` starts being useful.

```javascript
const person = {
    name: 'Alice',
    greet: function () {
        console.log("Hi, I'm " + this.name);
    }
};

person.greet(); // Hi, I'm Alice
```

`person` is calling `greet`, so `this` is `person`. That's it.

* * *

## How Calling Context Changes `this`

Here's the part that trips people up. Take the exact same function from above and pull it out of the object:

```javascript
const greet = person.greet;
greet(); // Hi, I'm undefined
```

Same function. Different caller. Now nobody owns the call, `this` falls back to the global object, and `name` isn't defined there.

This is the source of most `this` bugs. The function didn't change. The calling context did.

* * *

## `this` Inside Nested Functions

The problem compounds when you have a function inside a method.

```javascript
const person = {
    name: 'Alice',
    greet: function () {
        function inner() {
            console.log(this.name); // undefined
        }
        inner();
    }
};

person.greet();
```

`greet` is called by `person`, so `this` inside `greet` is `person`. But `inner` is called as a plain function with no owner, so `this` resets to the global object.

A common fix is to capture `this` before going in:

```javascript
const person = {
    name: 'Alice',
    greet: function () {
        const self = this;
        function inner() {
            console.log(self.name); // Alice
        }
        inner();
    }
};
```

Or just use an arrow function, which doesn't have its own `this` and inherits from the surrounding scope:

```javascript
const person = {
    name: 'Alice',
    greet: function () {
        const inner = () => {
            console.log(this.name); // Alice
        };
        inner();
    }
};
```

* * *

## Arrow Functions Don't Have Their Own `this`

Arrow functions inherit `this` from wherever they were defined, and nothing can change that.

```javascript
const person = {
    name: 'Alice',
    greet: () => {
        console.log(this.name); // undefined, always
    }
};

person.greet();
```

Even though `greet` is on `person`, it's an arrow function. `this` here is whatever `this` was in the outer scope when the object was created, not `person`. Arrow functions are great in a lot of situations, but if you need `this` to refer to the object, use a regular function.

* * *

## Summary

| Where `this` appears | What it refers to |
| --- | --- |
| Global function call | Global object (or `undefined` in strict mode) |
| Object method call | The object before the dot |
| Nested plain function | Global object (loses the outer `this`) |
| Arrow function | Inherited from surrounding scope |

* * *

Once you internalize "who called this function," most `this` surprises stop being surprises. The function is the same. The caller is what changes.
