this
Think about the word "I". When Ann says it, it means Ann; when Bob says it, it means Bob. The word itself does not remember who wrote it: its meaning is decided by whoever is speaking now.
The word this in a method works the same way. As you already know, a method called with a dot gets the object before the dot as this. But the same method stored in a constant loses its object:
"use strict";
const user = {
name: "Ann",
greet() {
return `Hi, ${this.name}`;
}
};
console.log(user.greet()); // Hi, Ann
const greet = user.greet;
console.log(greet()); // ✗TypeError: Cannot read properties of undefined (reading 'name')This is the Node.js and Chrome text; Firefox and Safari word the message differently. The first call prints Hi, Ann, the second stops the program.
The call decides this
this is decided at the moment of the call, not where the function is written. It is a common interview question: "What is this equal to?" For a regular function the answer starts with "it depends on how it was called". Let's look at three calls.
A call with a dot
In the call user.greet() the object before the dot is user, so this is user. user is the one saying "I", and this.name reads its name.
A call without a dot
The constant greet holds the same function, but the call greet() has no dot, and so it has no object. What ends up in this depends on the mode:
- in strict mode
thisisundefined, and readingundefined.namestops the program with aTypeError; - without
"use strict",thisgets the global object, a built-in object shared by the whole program.
In the second case there is no error, but the function still does not see the user's name.
A method as a callback
A method also loses its object when the method itself is passed as a callback. The call ["Bob"].forEach(user.greet) passes forEach only the function, and forEach calls it without a dot. It is like forwarding someone's message "I'll come" without a signature: you can no longer tell who "I" is.
The bind method
Every function has a bind method. The call user.greet.bind(user) does not run the function; it returns a new one whose this is always user, however it is called:
"use strict";
const user = {
name: "Ann",
greet() {
return `Hi, ${this.name}`;
}
};
const greet = user.greet.bind(user);
console.log(greet()); // Hi, Ann
console.log(["Bob", "Eve"].map(greet).join(" ")); // Hi, Ann Hi, AnnLet's go step by step:
user.greet.bind(user)returns a new function withuserbound to it for good.greet()is called without a dot, yet printsHi, Ann.mapgetsgreetas a callback and calls it for each element without a dot. Each timethisisuser, so both results areHi, Ann.
Arrow functions and this
An arrow function has no this of its own. It takes this from the code around it, the place where it is written. It has no "I" of its own: it speaks on behalf of the code it was written inside. That makes it a good callback inside a method:
"use strict";
const team = {
name: "Red",
members: ["Ann", "Bob"],
labels() {
return this.members.map((m) => `${m}-${this.name}`);
}
};
console.log(team.labels().join(" ")); // Ann-Red Bob-RedThe arrow function is written inside the method labels, so its this is the this of the method, that is team. A regular function (m) { … } in this place would be called by map without a dot, and its this would be undefined.
Here the analogy with the word "I" stops working: a person cannot speak with someone else's "I", while an arrow function does nothing else.
Common mistake
A method in an object literal — the name for curly braces { … } with keys and values — is made an arrow function:
const box = {
size: 3,
getSize: () => this.size // ✗
};
console.log(box.getSize()); // undefinedThere is no error, but the program prints undefined instead of 3. The arrow function takes this from the code around the literal, not from the object box. At the top level of a file in Node.js, this is an empty object, so this.size gives undefined, not an error. A call with a dot does not change that. If a method needs its own object, write it as a regular function, for example in the short form: getSize() { return this.size; }.
Key points
- The call decides
this: with a dot it is the object before the dot; without a dot, in strict mode, it isundefined. - A method stored in a variable or passed as a callback loses its object;
bindreturns a function withthisbound for good. - An arrow function has no
thisof its own: it takes it from the code around it, so it suits a callback in a method but not a method itself.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.