Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialkwame awuah
49 PointsWHY GETTERS?
i am totally confused here why do we need to use getters at all let alone setters? i am so used to guil hernardez so i find it difficult coping with new instructors
4 Answers
Daoud Merchant
5,135 PointsI can totally understand why 'getters' seem superfluous right now. If it helps, here are two quick real-world cases for a 'getter':
1: Creating properties which contain logic
Imagine a Person
class with firstName
and lastName
properties, where we will frequently be accessing the full name as the firstName
and lastName
separated by a space. With a 'getter', that logic can live on the class itself and the interpolated value can be accessed like a normal property:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
};
const richMan = new Person("Jeff", "Bezos");
richMan.fullName; // "Jeff Bezos"
richMan.firstName = "Jeffrey";
richMan.fullName; // "Jeffrey Bezos"
Remember, properties/values are, methods/functions do. Without get
, fullName
would need to be accessed by calling the function richMan.fullName()
. For anyone using your class, the interface for accessing the fullName
is much more intuitive with a 'getter'. It's as if we'd included a this.fullName
property in the constructor, but (as you see above) it will automatically update when a dependent property is updated. Had richman.fullName
been instantiated in the constructor, every time richMan.firstName
changed we'd also need to update richMan.fullName
.
2: Creating immutable values
This is a bit different from what you've seen in the lesson, but consider the following:
class ClassicalPerson {
constructor(name) {
this.name = name;
}
greet() {
return `Hi, I'm ${this.name}!`;
}
};
const jim = new ClassicalPerson("Jim");
jim.name; // "Jim";
jim.greet(); // "Hi, I'm Jim!"
jim.name = "Bob";
jim.name; // "Bob"
jim.greet(); // "Hi, I'm Bob!"
const FunctionalPerson = name => ({
get name() { // getter
return name;
},
greet() {
return `Hi, I'm ${name}!`;
}
});
const mike = FunctionalPerson("Mike");
mike.name; // "Mike";
mike.greet(); // "Hi, I'm Mike!"
mike.name = "Harry"; // fails
mike.name; // "Mike";
mike.greet(); // "Hi, I'm Mike!"
Note how in both instances the name is accessed just like a property - .name
. The big difference is that it cannot be set like a property when it's a getter. In other words, the name "Mike" lives within mike
, it is read and accessed through name
and greet
, but it cannot be changed after the initial function call. This sort of control over the object can help prevent major bugs while behaving just like a normal property.
I hope this helps!
Steven Parker
231,271 PointsWow, that's rather tricky, since the "name" in FunctionalPerson isn't an object property at all, but a function parameter. If I redefine it without the getter but with an expanded greet method it does this:
const FunctionalPerson = name => ({
greet() {
return `Hi, I'm ${name}! (or am I ${this.name}?)`;
}
});
const mike = FunctionalPerson("Mike");
mike.name = "Harry";
mike.greet(); // "Hi, I'm Mike! (or am I Harry?)"
What really surprised me was that before I made any changes, I tried dumping mike out in the JavaScript console, and it included this property: name: (...)
(not name: "Harry"
or name: "Mike"
)!
Daoud Merchant
5,135 PointsSteven Parker I'm sorry, I meant to clarify, not add further 'trickiness'! I was using a different pattern which I'll try to briefly explain for whomever it may help:
My example FunctionalPerson
was a factory function which:
- returns a new object
- does not use the generic object (populated with
this
) - is called like a normal function (
const person = Person("John")
)
Whereas a class or constructor function:
- populates an object within the context of where it's called (by using
this
) -
must be called with the 'new' operator (
const person = new Person("John")
) to create a new context and prevent all kinds of bugs! (Using theclass
syntax prevents calling without the 'new' keyword for this reason.)
Your example FunctionalPerson
effectively mixes the two approaches, which must be avoided by developers since a JavaScript engine won't catch it (it's a 'gotcha').
I hope this is clearer, I didn't mean to throw a spanner in the works! My apologies.
Edit: shortened for clarity
Steven Parker
231,271 PointsGetters (and setters) allow your object to have custom code internally, but to operate from the outside just as if they were ordinary properties. You don't actually need them, as you can do similar things with methods, but the syntax for using them will be different.
Being able to access them just like properties can be quite convenient, once you get used to them.
Nikola Lukic
8,061 PointsDaoud Merchant, I don't think that I understand the need (or preference) of a getter in the first example.
Am I not getting the same result as in your code block with the getter if I do this:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName} ${LastName}`: // defining the fullName in the constructor method
}
// get fullName() {
// return `${this.firstName} ${this.lastName}`;
// }
};
const richMan = new Person("Jeff", "Bezos");
richMan.fullName; // "Jeff Bezos"
richMan.firstName = "Jeffrey";
richMan.fullName; // "Jeffrey Bezos"
What is the benefit of using the getter over what I did above?
Steven Parker
231,271 PointsThe obvious difference is you did not define a getter for firstName.
If you do, you will still be able to read it, but not change it.
Daoud Merchant
5,135 PointsI'm afraid you won't get the same result, because this.fullName
is assigned the values from the constructor call ("Jeff" and "Bezos"), and therefore does not update itself when either firstName
or lastName
are changed (it contains values which were set and need to be reset manually rather than logic which recalculates a value every time the property is accessed (and the function is called).
Have you tried this out in the console? When I do I get:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName} ${lastName}`; // defining the fullName in the constructor method
}
};
const richMan = new Person("Jeff", "Bezos");
richMan.fullName; // "Jeff Bezos"
richMan.firstName = "Jeffrey";
richMan.fullName; // "Jeff Bezos" (does not update!)
Let me know if it's still unclear.
Nikola Lukic
8,061 PointsThanks Steven Parker and Daoud Merchant. I think I understand it a little better now re the updating itself part (watched some extra YT videos of it as well).
Siam Hossain
Full Stack JavaScript Techdegree Student 4,615 PointsSiam Hossain
Full Stack JavaScript Techdegree Student 4,615 PointsEncapsulation