# Losing this, and How Arrow Functions Help

When you hand a method to other code as a callback, it loses the object before the dot and this goes missing, and an arrow function or bind gives it back.

Journeyman · JavaScript · OOP · Updated November 1, 2026

## After this lesson you can

- Explain why this is lost when a method is passed as a callback
- Keep this in a callback with an arrow function or bind

## Key takeaways

- Passing comet.fire hands over the function only, not Comet. When it's called later with no dot, this is no longer Comet.
- Wrap the call in an arrow function, () => comet.fire(), so the dot comes back when it runs.
- bind makes a copy of a function with this fixed for good, as in comet.fire.bind(comet).
- An arrow function has no this of its own. It uses the this of the code around it, so it's the right choice for a callback inside a method.
- Write an object's own methods the regular way, not as arrow functions, or this won't be the object.

This is one of the bugs that trips up almost everyone who writes JavaScript. You hand a method to a button, a timer or a game's key handler, it runs, and `this` is suddenly not the object you meant: the ship's name prints as `undefined`, or the program stops with *Cannot read properties of undefined*. Once you know why it happens, it takes one small change to fix, and you'll spot it in other people's code too.

## The spacebar fires... somebody

Red Squadron's ships fire when the player presses the spacebar. The game has a function, `onSpacebar`, that takes an action and runs it when the key is pressed. A function you hand to other code, for it to call, is a **callback** (you met callbacks with `map` and `filter`). Here Comet fires once directly, and once as a callback:

```javascript
function onSpacebar(action) {
  console.log("Spacebar pressed");
  action();
}

const comet = {
  name: "Comet",
  missiles: 3,
  fire() {
    this.missiles = this.missiles - 1;
    console.log(`${this.name} fires! Missiles left: ${this.missiles}`);
  },
};

comet.fire();
onSpacebar(comet.fire);
```

```text
Comet fires! Missiles left: 2
Spacebar pressed
undefined fires! Missiles left: NaN
```

The first shot works. The second has no name and `NaN` missiles (*not a number*: what you get from `undefined - 1`). Same method, same ship. What changed?

## No dot, no object

Remember the rule from *Methods and this*: `this` is the object before the dot **when the method is called**. Look at how `onSpacebar` calls it: `action()`. There's no dot, so there's no object.

`comet.fire` without parentheses doesn't run anything. It reads the function out of Comet, like copying a recipe card out of a cookbook. You hand over the card, not the cook. It's like a sticky note that says *"my missiles are low"*: whoever reads it out loud, *my* means them.

You can see the same thing without a callback, by saving the method in a variable first:

```javascript
const comet = {
  name: "Comet",
  report() {
    console.log(`${this.name} reporting`);
  },
};

const report = comet.report;

comet.report();
report();
```

```text
Comet reporting
undefined reporting
```

What `this` becomes when there's no dot depends on where the code runs. In a plain `.js` file like this one, Node uses its older, forgiving mode, and `this` becomes Node's global object, which has no `name`, so you see `undefined`. Inside a class, and in files that are modules (such as this course's exercises), JavaScript is stricter: `this` is `undefined` itself, and the program stops with an error such as *TypeError: Cannot read properties of undefined (reading 'name')*. Both mean the same thing: the method lost its object.

**Try it.** Make `spacebar.js` with the first example and run it with `node spacebar.js`. Then add the line `console.log(comet.missiles);` at the end. Did the callback's shot use one of Comet's missiles?

## Fix 1: wrap it in an arrow function

The most common fix is to hand over a small function that makes the call *with* the dot. An **arrow function**, `() => comet.fire()` (the `=>` is read "arrow"), is a function with no parameters whose whole job is to call `comet.fire()`:

```javascript
function onSpacebar(action) {
  console.log("Spacebar pressed");
  action();
}

const comet = {
  name: "Comet",
  missiles: 3,
  fire() {
    this.missiles = this.missiles - 1;
    console.log(`${this.name} fires! Missiles left: ${this.missiles}`);
  },
};

onSpacebar(() => comet.fire());
onSpacebar(() => comet.fire());
```

```text
Spacebar pressed
Comet fires! Missiles left: 2
Spacebar pressed
Comet fires! Missiles left: 1
```

`onSpacebar` still calls `action()` with no dot. But `action` is now the arrow function, and when it runs, it calls `comet.fire()`: Comet is back before the dot.

## Fix 2: bind

Every function has a method named **`bind`**. `comet.fire.bind(comet)` makes a copy of `fire` whose `this` is fixed to Comet for good, however it's called later:

```javascript
function onSpacebar(action) {
  console.log("Spacebar pressed");
  action();
}

const comet = {
  name: "Comet",
  missiles: 3,
  fire() {
    this.missiles = this.missiles - 1;
    console.log(`${this.name} fires! Missiles left: ${this.missiles}`);
  },
};

const cometFire = comet.fire.bind(comet);
onSpacebar(cometFire);
onSpacebar(cometFire);
```

```text
Spacebar pressed
Comet fires! Missiles left: 2
Spacebar pressed
Comet fires! Missiles left: 1
```

`bind` is handy when you want to keep the fixed copy in a variable and hand it out more than once. Two relatives you may meet in older code, `call` and `apply`, run a function once, right away, with the `this` you give them: `comet.fire.call(comet)`.

## Arrow functions inside methods

The same bug hides inside methods that use callbacks. Red Squadron's `rollCall` goes through its ships with `forEach`, and the callback is written with the `function` keyword:

```javascript
const squadron = {
  name: "Red Squadron",
  ships: ["Comet", "Vega", "Orion"],
  rollCall() {
    this.ships.forEach(function (ship) {
      console.log(`${this.name}: ${ship}`);
    });
  },
};

squadron.rollCall();
```

```text
undefined: Comet
undefined: Vega
undefined: Orion
```

`this.ships` works, because `rollCall` was called as `squadron.rollCall()`. But `forEach` calls the inner function with no dot, so inside it, `this` is lost.

An arrow function fixes it, because **an arrow function has no `this` of its own**. It uses the `this` of the code around it, like a passenger who goes wherever the car goes. Around it is `rollCall`, where `this` is the squadron:

```javascript
const squadron = {
  name: "Red Squadron",
  ships: ["Comet", "Vega", "Orion"],
  rollCall() {
    this.ships.forEach((ship) => {
      console.log(`${this.name}: ${ship}`);
    });
  },
};

squadron.rollCall();
```

```text
Red Squadron: Comet
Red Squadron: Vega
Red Squadron: Orion
```

That's why arrow functions are the usual choice for callbacks inside methods: `map`, `filter`, `forEach`, timers and click handlers.

## Don't make the method itself an arrow

Because an arrow function takes `this` from the code around it, it's the wrong choice for the method itself. Here `report` is an arrow function, and the code around it is the file, not Vega:

```javascript
const vega = {
  name: "Vega",
  report: () => {
    console.log(`${this.name} reporting`);
  },
};

vega.report();
```

```text
undefined reporting
```

`vega.report()` has Vega before the dot, but an arrow function ignores the dot. The rule of thumb: **write an object's own methods the regular way, and use arrow functions for the callbacks inside them.**

![A ship handing a sealed order card to the spacebar: with no ship's name on the card, the spacebar doesn't know who should fire; a card that says "Comet, fire" works wherever it goes](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/10/765ddd9ceeb94394a7119e0c656e4da0.webp)

**Try it.** In `spacebar.js`, replace `onSpacebar(comet.fire)` with each fix in turn, the arrow function and then `bind`, and run it each time. Then turn `fire` itself into an arrow function, `fire: () => { ... }`, and run it again. Which of the three works?

## Check yourself

2 questions to try on the lesson page.

## So what

Any time you hand a method to something else (a button, a timer, `map`, a game loop), ask "who will be before the dot when it runs?" If the answer is nobody, wrap it in an arrow function or `bind` it, and `this` stays the object you meant.

## Key terms

- [this](https://www.ask-codey.com/glossary/this-javascript)
- [Arrow Function](https://www.ask-codey.com/glossary/arrow-function)
- [Callback Function](https://www.ask-codey.com/glossary/callback-function)
- bind()

## Cheat sheets

- [Losing this, and How Arrow Functions Help](https://www.ask-codey.com/cheat-sheets/javascript-this-arrow-functions-and-this-cheat-sheet)

## Related

- [Methods and this](https://www.ask-codey.com/lessons/javascript-this-methods-and-this)
- [Classes: Blueprints for Objects](https://www.ask-codey.com/lessons/javascript-classes-blueprints)

Source: https://www.ask-codey.com/lessons/javascript-this-arrow-functions-and-this
