learn.colinkim.dev

Methods and this

Learn how methods access the object they belong to, what the this keyword actually refers to, and the common scenarios where it causes confusion.

Methods are functions stored as object properties. When you call a method, JavaScript sets the this keyword to the object the method was called on.

Understanding this is one of the most confusing parts of JavaScript. It becomes simple once you learn the rules.

this in methods

When a function is called as a method, this refers to the object before the dot:

const counter = {
  count: 0,
  increment() {
    this.count++;
    return this.count;
  },
};

counter.increment();  // 1
counter.increment();  // 2

Inside increment, this refers to counter because the call was counter.increment(). The object before the dot becomes this.

this depends on how a function is called

The same function can have different this values depending on how it is invoked:

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

const obj = { showThis };

showThis();       // global object (or undefined in strict mode)
obj.showThis();   // obj

The function is the same. What changes is the call site. this is determined at call time, not at definition time.

Losing this in callbacks

The most common this bug happens when you pass a method as a callback:

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

setTimeout(counter.increment, 100);
// TypeError: Cannot read properties of undefined (reading 'count')

When counter.increment is passed to setTimeout, it is called as a plain function, not as a method. There is no object before the dot, so this is undefined (in strict mode) or the global object.

Fix 1: Use an arrow function wrapper

setTimeout(() => counter.increment(), 100);
// works — increment is called as counter.increment()

Fix 2: Use bind

bind creates a new function with this permanently set:

setTimeout(counter.increment.bind(counter), 100);
// works — this is bound to counter

Fix 3: Use arrow function methods

Arrow functions do not have their own this — they inherit it from the surrounding scope:

const counter = {
  count: 0,
  increment: function() {
    this.count++;
  },
};

This does not change anything because increment is a regular function. But when you use arrow functions in callbacks inside methods, this is preserved:

const counter = {
  count: 0,
  start() {
    setInterval(() => {
      this.count++;  // arrow inherits `this` from start(), where this = counter
    }, 1000);
  },
};

this in the global context

In the global context (code not inside a function), this refers to the global object:

console.log(this);  // window in browsers, global in Node.js

In strict mode (which modules use by default), this is undefined in the global context:

"use strict";
console.log(this);  // undefined

this in event handlers

In DOM event handlers, this refers to the element that the listener is attached to:

button.addEventListener("click", function() {
  console.log(this);  // the button element
});

If you use an arrow function for the event handler, this is inherited from the surrounding scope instead:

button.addEventListener("click", () => {
  console.log(this);  // whatever `this` was in the outer scope
});

Use regular functions when you need this to be the element. Use arrow functions when you need this to be the component or object the handler belongs to.

Rules for determining this

  1. Method call (obj.method()) — this is the object before the dot
  2. Plain function call (func()) — this is undefined (strict mode) or the global object
  3. Arrow functionthis is inherited from the enclosing scope
  4. bindthis is whatever you passed to bind
  5. call / applythis is the first argument passed to the method
  6. Event handler (regular function)this is the element the listener is on
  7. Event handler (arrow function)this is inherited from the outer scope
const counter = {
  count: 0,
  increment: () => {
    this.count++;  // this is NOT counter — it is undefined or global
  },
};

Use regular function syntax for object methods. Use arrow functions for callbacks inside those methods.

What to carry forward

  • this refers to the object the method was called on — the object before the dot
  • this is determined at call time, not definition time
  • passing a method as a callback loses the this binding
  • fix lost this with arrow function wrappers, bind, or arrow function callbacks
  • arrow functions do not have their own this — they inherit from the enclosing scope
  • in event handlers, this is the element for regular functions, inherited for arrow functions
  • use regular functions for object methods; use arrow functions for callbacks

Understanding this is essential for working with objects, classes, and DOM event handlers. The next lesson covers the prototype chain in more depth.

Quick Check

One answer

What mainly determines the value of this for a regular JavaScript function?

Choose the best answer and use it to track your progress through the lesson.

Progress

Quick checks

No quick checks in this lesson.

Mark lesson manually or answer quick checks to track progress.