Towards understanding JavaScript’s this

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:
- new
- explicit/hard
- implicit
- 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:
- new
- explicit/hard
- implicit
- 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 🐦