Towards understanding JavaScript’s this

faraz amiruddin
3 min readMay 28, 2019
“You Got This” — Photo by sydney Rae on Unsplash

JavaScript’s this confuses me.

I've been studying You Don’t Know JS to get a better understanding. These are my takeaways.

The main thing to remember is what this references is determined by how the function is called.

Why this?

In order to understand this, let's talk about why it exists in the first place.

this allows you to write a function and apply different contexts to it, without having to write a function for each context.

function greeting() {
return "Hello, I'm " + this.name;
}
var me = { name: "Faraz" };
var you = { name: "Saad" };
console.log(greeting.call(me)); // "Hello, I'm Faraz"
console.log(greeting.call(you)); // "Hello, I'm Saad"

We’re using the built in .call() method to explicitly use me or you as the this reference.

To learn more about .call(), check out MDN:

What this isn't

There are a couple things that this is often confused for.

this is not itself

this does not refer to itself. If you want to access a named function from inside itself, you can use it's name property.

function upperCase(t) {
upperCase.count++; // referring to itself.
return t.toUpperCase();
}
upperCase.count = 0;
var teletubbies = ["Dipsy", "Laa-Laa", "Po", "Tinky Winky"];for (var i = 0; i < teletubbies.length; i++) {
console.log(upperCase(teletubbies[i]));
// DIPSY, LAA-LAA, PO, TINKY WINKY
}
console.log(upperCase.count); // 4

Note: You can’t access an anonymous function from inside itself, because it doesn’t have a name.

setTimeout(function () {
// can't access itself because it doesn't have a name.
}, 100);

this is not it's scope

this does not mean the function's scope. You can't bridge a function's scope with this.

function foo() {
var a = 2;
bar();
}
function bar() {
console.log(this.a); // you can't do this, `a` doesn't exist here.
}
console.log(foo()); // undefined

So, what is this?

When a function is invoked, an execution context is created. This execution context contains:

  • Where the function was called (a.k.a the call-stack)
  • How the function was called (what parameters were passed, etc)
  • One property of the execution context is the this reference which will be used for the function's duration.

🌟 The `this` binding is made when the function is invoked, and what it references depends on the call-site.

Call-site

Where the function is called.

function foo() {
console.log("foo");
bar(); // <-- bar's call-site
return;
}
function bar() {
console.log("bar");
return;
}
foo(); // <-- foo's call-site

Determining `this` in order of precedence

We use the call-site and this order of precedence to determine what this references.

The order of precedence is as follows:

  1. new
  2. explicit/hard
  3. implicit
  4. default

Let’s go over each, in reverse order:

(4) Default: Here, foo() is invoked in the global context. In strict mode, it’s undefined , otherwise use the global object.

foo(); // in the browser, this is the window

(3) Implicit: Is the function implicitly called via an object? this is that object.

obj.foo(); // this is obj

(2) Explicit/Hard: Is the function explicitly called with call or apply (explicit), or hard bound with bind (hard)? this is the specified object.

// explicit binding 
foo.call(obj);
foo.apply(obj);
// hard binding
foo.bind(obj);
foo();
// this is obj

(1) New binding: Is the function called with new? this is the newly constructed object.

var car = new Car(); // this is car

To recap, the order of precedence is:

  1. new
  2. explicit/hard
  3. implicit
  4. default

Arrow functions and lexical this

Arrow functions adopt the this binding from the enclosing function or global scope.

The lexical binding of an arrow function cannot be overwritten, even with new.

Arrow functions are essentially syntactic sugar for var self = this;

function foo() {
setTimeout(() => {
console.log(this.name);
// `this` is lexically adopted from `foo()`
}, 100);
}
var person = { name: "Col. Samford Smithers" };foo.call(person); // Col. Samford Smithers

Thanks for reading! If you enjoyed this post, please make sure to clap and share 👏

If you’d like me to write about something specific, submit a question to my ask-me-anything

You can find me on twitter @farazamiruddin 🐦

--

--

faraz amiruddin

software engineer. building retro.app in public. love react x firebase.