Article Image
Article Image
read

There is a common problem all JS developers run into at some point.

The this binding is tricky to use. The power (and confusion) of this stems from the fact that it can be bound to different things depending on how the function or method is called. In some instances, though, it seems like the code completely forgets what the this binding refers to.

Most of the time, you can assume that it will be bound to whatever is to the left of the calltime dot (the dot right before the method call)

var obj = {
  met: function() {
    console.log(this);
  }
}
obj.met() // logs the object

Following this logic, it would make sense that the binding would stay the same when using setTimeout() or setInterval().

setTimeout(obj.met, 1000);
// Logs ???

However, because of what’s going on under the hood, this will refer to the global window object in the browser, NOT the object.

Under the hood

The reason this happens is because setTimeout executes the callback function you give it (in our case, obj.met) inside of a different execution context. An excellent description of what an execution context can be found here. In short, it basically means the scope the function is being evaluated in at runtime is much different than the what the scope looks like in code. Our expectation that the in-memory models of our code will be laid out like the code on our screen is flawed, and thinking in terms of execution contexts can help when running into problems like this.

The solution(s) to this problem

There are a few ways to successfully refer to this in the right context when using these functions.

One way is to wrap the method call inside of an anonymous function:

setTimeout(function() {
  obj.met(); // make sure to call the method with ()
}, 1000)

// Logs `obj` correctly

Another way is to bind the object that we want this to refer to, to the method inside of setTimeout:

setTimeout(
  obj.met.bind(obj);
, 1000)

Interestingly enough, these two examples do exactly the same time. All bind does is wrap the function it is called on inside of an anonymous function. Personally, I like to use bind, as I think it makes the code a lot cleaner. However, you should use whichever way you like best.

Blog Logo

Kamerynn Harrah


Published

Image

Kamerynn Harrah

code. and sometimes lame jokes

Back to Overview