Methods and this
A method is a function that belongs to an object, and inside it the word this means the object before the dot, so one method can work on whichever object calls it.
Apprentice · JavaScript · OOP · Updated
After this lesson you can
- Write a method on an object and call it with a dot
- Predict what this refers to inside a method from the object before the dot
Key takeaways
- A method is a function stored in an object. You call it with the object's name, a dot and parentheses, as in comet.takeHit(30).
- You've used methods since your first program. console.log, toUpperCase and push are all methods.
- Inside a method, this is the object before the dot. With comet.report(), this is comet.
- Write this.shields, not comet.shields, so the same method works for every object that has it.
In a game, a ship doesn't only have things (a name, shields, fuel). It also does things: it launches, takes a hit and fires. A shopping cart adds items and works out its total; a music player plays, pauses and skips. Every app you'll write needs objects that do things with their own data, and in this lesson you build them.
This chapter's running example is a space shooter game: the player flies Red Squadron, a fleet of ships such as Comet, Vega and Nova. Every lesson in the chapter works on its ships.
An object that can do something
Think of a TV remote. It has things you can read, such as the brand on the back, and buttons that do something. The buttons belong to that remote.
An object can hold a function as well as values. A function that belongs to an object is called a method. You write it inside the object's curly braces, with its name, parentheses and a body, and you call it with the object's name, a dot and parentheses:
const comet = {
name: "Comet",
shields: 100,
launch() {
console.log("3, 2, 1... launch!");
},
};
console.log(comet.name);
comet.launch();
Comet
3, 2, 1... launch!
comet.name reads a value; comet.launch() runs the method. The parentheses make the difference: they say "run it now". Notice the comma after the method's closing }, as after any other property.
In older code you'll also see the long way of writing the same method, launch: function () { ... }. Both make a method.
You've used methods all along
That dot-and-parentheses shape should look familiar. You've been calling methods since your first program:
const callSign = "comet";
const enemies = ["drone", "scout"];
console.log(callSign.toUpperCase());
enemies.push("mothership");
console.log(enemies.length);
console.log(Math.max(40, 75, 60));
COMET
3
75
console is an object, and log is its method. toUpperCase is a method every string has, push a method every array has, and max a method of the built-in Math object (it gives back the biggest number you hand it). Now you can write your own.
Try it. Make a file named ship.js with the comet object from the first example. Add a second method, land(), that prints Comet is back in the hangar., call it after launch(), and run the file with node ship.js.
this: the object before the dot
A method that only prints a fixed message isn't very useful. A real takeHit method needs the ship's own shields: it lowers them and says what's left.
When you say "my shields are low", the word my means whoever is talking. JavaScript has a word like that: this. Inside a method, this means the object before the dot when the method was called. In comet.takeHit(30), the object before the dot is comet, so this is comet:
const comet = {
name: "Comet",
shields: 100,
takeHit(damage) {
this.shields = this.shields - damage;
console.log(`${this.name} is hit! Shields: ${this.shields}`);
},
};
comet.takeHit(30);
comet.takeHit(25);
console.log(comet.shields);
Comet is hit! Shields: 70
Comet is hit! Shields: 45
45
this.shields is Comet's own shields property, so the method changes the object it belongs to. The last line shows the change stuck: Comet has 45 left.
One method, many objects
Why not write comet.shields inside the method? Because then the method only ever works on Comet. With this, one function can serve every ship. Here a single report function is stored in two ships:
function report() {
console.log(`${this.name}: shields ${this.shields}`);
}
const comet = { name: "Comet", shields: 45, report: report };
const nova = { name: "Nova", shields: 100, report: report };
comet.report();
nova.report();
Comet: shields 45
Nova: shields 100
It's the same function both times. What changes is the object before the dot: comet.report() makes this Comet, and nova.report() makes this Nova. That's the rule to remember: this is decided when the method is called, by the object before the dot, not by where the function was written.
Here's the bug that this saves you from. This report names Comet instead of using this:
const nova = {
name: "Nova",
shields: 100,
report() {
console.log(`${comet.name}: shields ${comet.shields}`);
},
};
const comet = { name: "Comet", shields: 45 };
nova.report();
Comet: shields 45
Nova reports Comet's shields. Nothing crashes, so a bug like this can hide for a long time.
Methods that use each other
A method can call another method of the same object, with this and a dot. Vega's launch asks its own canFly method first:
const vega = {
name: "Vega",
shields: 20,
fuel: 0,
canFly() {
return this.shields > 0 && this.fuel > 0;
},
launch() {
if (this.canFly()) {
console.log(`${this.name} launches!`);
} else {
console.log(`${this.name} can't launch: check shields and fuel.`);
}
},
};
vega.launch();
vega.fuel = 60;
vega.launch();
Vega can't launch: check shields and fuel.
Vega launches!
Inside launch, this is Vega, so this.canFly() calls Vega's own canFly, which reads Vega's own shields and fuel. With no fuel she stays put; after vega.fuel = 60; she's off.
Try it. Add a refuel(amount) method to Vega that adds amount to this.fuel and prints the new fuel. Start Vega with no fuel, call vega.launch(), then vega.refuel(40), then vega.launch() again.
Check yourself
2 questions to try on the lesson page.
So what
Objects that keep their data and the actions on it together are how real programs are organized: a cart and its total, a player and their score, a ship and its shields. this is what lets one method work for every one of them, and the next lesson shows the one place it can let you down.