Making Sense of 'this' and More in JavaScript!

What is this mysterious this keyword that keeps showing up? Let's find out and get really good at using it!


This is a companion discussion topic for the original entry at https://www.kirupa.com/javascript/this_that_arrow_functions_bind.htm

You should add @senocular ‘s flow chart of this…. :smile:

But then you might have to change the title to:
WTF is “this”?!… an engineers guide. :smile:

1 Like

Some comments:


let myObject = {
  name: "Iron Man",
  whatIsThis: function () {
    console.log(name); // won't work!
  }
};
myObject.whatIsThis(); // undefined

You have to be careful with examples like these. What you end up getting is not undefined, rather whatever the name is of the current browser window/frame since name is a global property in browsers. For example, if you pasted this code in a jsfiddle and ran it, you’d see the output of "result". In most other browser windows it’ll usually be an empty string because that is the default of window.name. And if you’re not in a browser, running in some environment that doesn’t have a global name, you’d get an error.

// NodeJS
let myObject = {
  name: "Iron Man",
  whatIsThis: function () {
    console.log(name);
  }
};
myObject.whatIsThis(); // ReferenceError: name is not defined

The reason is that traditional functions don’t behave in this seemingly logical way. They define their own value for this and that is always going to refer to the context they are being used in.

Not the context they’re being used in, but how they’re called. The only time they use the context they’re being used in is when called in global, and that just so happens to be because default binding uses the global object. And, well, this kind of applies to modules too because their context is undefined but modules are also always in strict mode which means the default binding will use undefined instead of window. So in that case it technically matches too :stuck_out_tongue: . In any function context, function calls would not refer to that context unless explicitly told to or using an arrow function that also happened to be defined in that same context (except then there’s no binding, its just grabbing this from the scope).


Our anonymous function inside our setInterval doesn’t get created when our counter object is initialized. It gets created only when we call the startCounting method:

counter.startCounting();

This call lives in the context of the window object. When startCounting is invoked and the anonymous function is created, the this.initial call is looking for the value of initial on the window object.

This one is a little tricky and I’m not quite sure about the wording here. Specifically

This call lives in the context of the window object.

While the call is happening in the global scope/context, it has no bearing on what the setInterval callback is doing. And yes, while it ends up looking for initial on the window object, the blame for that is entirely on setInterval. It defaults to calling callbacks specifically through window (or the Timeout object in Node) and not using the default binding. You can see the difference in strict mode when the default binding gives you a this of undefined but through setInterval (and setTimeout) you still get window.

"use strict";
function test (label) {
  console.log(label, this)
}
test("normal")
setTimeout(test, 0, "timeout")
// normal undefined
// timeout Window { ... }

The timeout functions are effectively doing a callback.call(window) in the background rather than calling the function normally. That, in turn, can cause some unexpected behavior when trying to explain the behavior of this.


Beyond not having their own this value (which they inherit from their surroundings), arrow functions have no constructor or prototype properties.

While they have no prototype property, they do have a constructor. What they don’t have their own of includes: this, arguments, super, and new.target.


They also don’t support the bind, call, and apply methods.

They support these methods, but these methods can’t be used to change the this value in an arrow function.

const add = (a, b) => a + b
console.log(add.call(null, 1, 2)) // 3

When called, what bind creates is a new function known as a bound (or exotic ) function

I’d be careful with the use of “exotic” here. While bound functions are exotic not all exotic functions are necessarily bound. In fact arrays are exotic (exotic objects, not functions). Exotic values are simply values that have unique, internal behavior to them.


As we’ve seen with the flowchart for this it’s a messy, complicated topic :wink:

This is excellent feedback, sen! I’ll incorporate your comments into this article shortly.