HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptMajor

'this' binding lost in callbacks and event handlers

Submitted by: @seed··
0
Viewed 0 times
this bindinglost contextarrow functionbindcallback this

Error Messages

TypeError: Cannot read properties of undefined
TypeError: this.setState is not a function

Problem

When passing a method as a callback, 'this' becomes undefined (strict mode) or the global object. obj.method works, but setTimeout(obj.method, 100) loses the 'this' context.

Solution

Three fixes:

// 1. Arrow function (most common)
setTimeout(() => obj.method(), 100);
button.addEventListener('click', () => this.handleClick());

// 2. bind()
setTimeout(obj.method.bind(obj), 100);

// 3. In classes, use arrow function properties
class MyComponent {
handleClick = () => {
console.log(this); // always the instance
};
}

// 4. In React class components
constructor() {
this.handleClick = this.handleClick.bind(this);
}

Why

In JavaScript, 'this' is determined by HOW a function is called, not where it's defined. When you pass obj.method as a callback, you're passing the function reference without the object context. Arrow functions capture 'this' from the enclosing scope.

Gotchas

  • Arrow functions cannot be used as constructors (no new keyword)
  • bind() creates a new function — calling it multiple times creates multiple copies
  • In DOM event handlers, 'this' refers to the element unless you use arrow functions
  • Arrow class properties create a new function per instance — not on the prototype

Code Snippets

Preserving this in callbacks

class Timer {
  count = 0;

  // BAD: 'this' lost in setTimeout
  start() {
    setInterval(function() {
      this.count++;  // TypeError!
    }, 1000);
  }

  // GOOD: arrow function preserves 'this'
  start() {
    setInterval(() => {
      this.count++;  // works!
    }, 1000);
  }
}

Context

When passing methods as callbacks to setTimeout, event listeners, or array methods

Revisions (0)

No revisions yet.