Use getters and setters for an alternative syntax to traditional class methods

Hello,

So I have finally understood how constructors, getters and setters work but I have a couple questions still.

In the example they provided and challenge, both the setter and getter use the same property name (‘temperature’ and ‘writer’). So say we want to update the author, do we simply make the instance of the class with the parameter (‘writer’) equal our new desired author like below?

const novel = new Book('anonymous');

**novel.writer = 'newAuthor'**

If so, wouldnt it be better to name one parameter ‘updatedWriter’? (**novel.updatedWriter = 'newAuthor'**) or do they have to have the same parameter name and if so, why?

Also, I don’t get the point of the getter if its simply returning the value we passed in from the instance. In the challenge it converts the value into Celsius so I see why its helpful there. But what does the setter do here? The equation is simply for Converting Celsius into Fahrenheit but doesnt actually pass in Celcius, it just states Celcius.

I don’t understand how they’re using this.temperature. For the getter I understand they’re passing in the value 76 from the instance. But for the setter, which of the below are they staing?

76 = (celsius * 9.0) / 5 + 32;

OR

this.temperature = (celsius * 9.0) / 5 + 32; where this.temperature refers to the variable, not its value so that the variable now has the value after the operator.

Thank you

  **Your code so far**

class Thermostat {
constructor(fahrenheit) {
  this.fahrenheit = fahrenheit;
}

get temperature() {
  return (5 / 9) * (this.fahrenheit - 32);
}

set temperature(celsius) {
  this.fahrenheit = (celsius * 9.0) / 5 + 32;
}
}
const thermos = new Thermostat(76); // Setting in Fahrenheit scale
let temp = thermos.temperature; // 24.44 in Celsius
thermos.temperature = 26;
temp = thermos.temperature; // 26 in Celsius


  **Your browser information:**

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36 Edg/94.0.992.50

Challenge: Use getters and setters to Control Access to an Object

Link to the challenge:

the instance of the class with the parameter (‘writer’) equal our new desired author like below?

novel.writer = 'newAuthor'

Yes, exactly. Since we are assigning the value, JS says, “OK, where’s the property ‘writer’? There isn’t one? That’s OK, there is a getter and setter for that “pseudo” property. Since we’re assigning that value, we’ll pass “newAuthor” onto the setter and it will know what to do.”

For something like this:

console.log(novel.writer);

We aren’t setting the value but are accessing it, retrieving it, getting it, so JS uses the getter.

If so, wouldnt it be better to name one parameter ‘updatedWriter’? (**novel.updatedWriter = 'newAuthor'**) or do they have to have the same parameter name and if so, why?

I’m not sure I completely understand. We want a property “writer”. We could just have a prop called “writer”. But then the user could do whatever they want. So, we hide them behind a getter/setter so we can control the access. We want the getter and setter to have the name of our “pseudo” property name that the user will access. True, JS could have given them different names. But JS decided to give them the same name to create a seamless usage - you use it just like you would a normal property.

Also, I don’t get the point of the getter if its simply returning the value we passed in from the instance.

Sure, in this case it doesn’t make sense. But maybe we have the end user set in the settings what units they want: celcius, fahrenheit, etc. We could put logic into the getter to check that and return a value according to that. Maybe we don’t want to let them access that data unless they’ve signed the ToS. The point is that with a getter we can control how they access that variable.

I don’t understand how they’re using this.temperature .

The “this” tells it to use the property on “this” class.

But for the setter, which of the below are they staing?

76 = (celsius * 9.0) / 5 + 32;

That’s just math. The instructions say:

Remember that C = 5/9 * (F - 32) and F = C * 9.0 / 5 + 32 , where F is the value of temperature in Fahrenheit, and C is the value of the same temperature in Celsius.

Those two formulas are just algebraic manipulations of each other. You have an unneeded set of parentheses in the setter, but they’re not hurting anything.

where this.temperature refers to the variable, not its value so that the variable now has the value after the operator.

I’m not sure I understand that. I think you are asking … That formula will be evaluated when the setter is called. The formula doesn’t get stored in this.temperature, the result of the calculation does.

“If so, wouldnt it be better to name one parameter ‘updatedWriter’? (**novel.updatedWriter = 'newAuthor'**) or do they have to have the same parameter name and if so, why?”

Using the example they provided, what I mean is that since both the setter and getter both use ‘writer’ how would javascript know whether to return the getter or the setter when we console.log(novel.writer)?

Also, I dont understand how the setter works in the challenge. We pass in a value in Celsius but from where? Do we use the value of the getter? and if so how?

Same as any other object property, that’s what getters/setters are designed to work exactly like.

If you’ve got an object, and it has the property writer, like

novel = {
  writer: "Russell Hoban"
}

And you run console.log(novel.writer), that will not set the property writer, you do that like

novel.writer = "Dino Buzzati"

That’s what a getter/setter pair act like, they are designed to look exactly the same as the above when the object is used.

Because it knows if it is assigning a value or returning a value. If I have:

foo = 127

I am assigning a value.

If I have:

val = foo

then I am retrieving the value of foo. JS knows the difference because it has to completely deconstruct and understand the code to use it.

If you wanted to learn more, you could learn how language parsers work, but that is a whole different field of study.

In some languages is is “clearer”. For example, I think in Java it would be “setWriter” and “getWriter” - it is more clear. The writers in JS realized, “Hey we can figure it out from how it’s being used. Let them just treat it as a regular property and JS can figure out whether to use the getter or setter.”

When you get more experience with the language, you’ll be able to look at the code and tell where the getter is used and where the setter is used. For now, don’t worry about it. Just use it like you would a normal property and let JS worry about the details.

I understand this because its an actual object that we have learned. But in this challenge, whereas writer is a property in the example object you gave, here novel is the variable. So do classes make it so variables using the new keyword act similarly to properties inside an object where you can reassign the value of the variable by accessing the setter using dot notation like below?
variable.setterName= desiredoutput

In JS, a class is really just a blueprint for an object. There’s a little bit more to it, but under the covers, it’s just an object. Everything in JS that isn’t a primitive is some kind of object.

So do classes make it so variables using the new keyword act similarly to properties inside an object…

The new keyword tells the JS to use that blueprint to create a new instance of the class.

… where you can reassign the value of the variable by accessing the setter using dot notation like below?

You don’t have to use getters and setters. You can still access properties like you would in a simple object. Getters and setters are just another tool that is available to you.

I could do:

class Person {
  constructor(name) {
    this.name = name;
  }
}

or I could do:

class Person {
  constructor(n) {
    this._name = n;
  }
  set name(n) {
    this._name = n;
  }
  get name(n) {
    return this._name;
  }
}

Both would work the same. The part of the code using it couldn’t tell the difference. Why do getters/setters? In this case it doesn’t matter, but if I wanted more control, I could control access to the “hidden” variable _name.

In JS we access getters and setters like they are “normal” properties. Not all languages do that. It’s just what JS decided to do.

Hey @floresruuben, everything posted above is great info and hopefully it answered your questions. I don’t have anything to add to those discussions, I just wanted to point out that I think the title of this challenge is misleading and perhaps is contributing to some confusion.

Use getters and setters to Control Access to an Object

I understand the sentiment behind this title but technically it is not true. Getters/Setters in JS do not provide any magical powers that allow you to control access to an object. They merely provide a slightly more convenient way to call a method on an object.

What does allow you to control access to fields in a class is the recently added private class features, But these are so new that I understand why FCC hasn’t updated the curriculum to include them. But even with private fields, you don’t have to use getters/setters to access them, you can use plain old boring regular class methods.

So I guess I’m saying that the title of this challenge should really be something like:

Use getters and setters for an alternative syntax to traditional class methods

Ah, I see, I think I have finally understand get, set is the one I’m still so confused on how it works. From previous replies, I now know that get does not mutate the value of the private variable, it simply returns it.

But how do we use setters? I tested it out with the following code

const thermos = new Thermostat(76);

console.log(thermos.temperature);

thermos.temperature = 26;

console.log(thermos.temperature)

The last console log logs out 26, I was under the impression since it utilzied the setter it would return the formula that we set in the class function so that we get 78.8 (the value of 26 Celcius in Fahrenheit)

The instructions for this challenge say:

" In the class, create a getter to obtain the temperature in Celsius and a setter to set the temperature in Celsius."

So the getter is always returning a value in C.

Right, but the formula they made us input inside the setter is to return Fahrenheit because we pass in Celsius

set temperatureCS(celsius) {

    this.fahrenheit = (celsius * 9.0) / 5 + 32;

  }

Ahh, the setter doesn’t return a value, it sets a value on a field in the class ( this.fahrenheit in this case).

The line:

console.log(thermos.temperature)

isn’t calling the setter, it is calling the getter.

So the setter mutates the value of the getter? Which is why when we console log (thermos.temperature), we get the mutated value?

If so, then how could we make it so we return the value from the equation

Not sure I would go that far. They do provide an API surface that allows some control over the property access.

But protection is not the correct way of thinking about it, just some control. Like what happens when a user of the API sets or gets a property.

If you use closure, or private fields, and control how properties are accessed you do have some protection as well. You might also freeze the object, or use a Proxy.

No, JS can’t store “formulas”. That is not a valid JS data type. I mean, functions are kind of formulas, but when you have something like this:

this.fahrenheit = (celsius * 9.0) / 5 + 32;

JS sees the assignment operator (=) and evaluates the right side ((celsius * 9.0) / 5 + 32) and assigns it to the left side (this.fahrenheit).

So the setter mutates the value of the getter? Which is why when we console log (thermos.temperature), we get the mutated value?

Not. The setter is this:

set temperature(celsius) {
  this.fahrenheit = (celsius * 9.0) / 5 + 32;
}

so it is changing (mutating) the class property, this.fahrenheit.

No, the setter mutates the value of the class field this.fahrenheit. Since you pass a value in Celsius into the setter it has to convert it to Fahrenheit before it sets this.fahrenheit.

The getter returns the value of this.fahrenheit but converts it to Celsius first.

I’m not sure what equation you are referring to? You are storing the temperature internally in F, so if you wanted to return the temperature in F then you could access it directly (thermos.fahrenheit) or write a method to get it [thermos.getFahrenheit()] or even use a setter (thermos.fahr).

So why doesnt

set temperature(celsius) {
  this.fahrenheit = (celsius * 9.0) / 5 + 32;
}

return 78.8 when we do this (what’s inside the ** **)

const thermos = new Thermostat(76);

console.log(thermos.temperature);

**thermos.temperature = 26**;

Isnt the 26 being passed into the setter’s parameter (celcius)?

So why doesnt

 set temperature(celsius) {
    this.fahrenheit = (celsius * 9.0) / 5 + 32;
 }

return 78.8 when we do this (what’s inside the ** **)

Because the setter converts it to 78.8 to store it and then the getter converts it back.

class Thermostat {
  constructor(fahrenheit) {
    this.fahrenheit = fahrenheit;
  }
  get temperature() {
    return (5 / 9) * (this.fahrenheit - 32);
  }
  set temperature(celsius) {
    this.fahrenheit = (celsius * 9.0) / 5 + 32;
  }
}

const thermos = new Thermostat(76); // setting in fahrenheit, because that's what the constructor does
console.log(thermos.temperature); // 24.444444444444446 the setter returns celcius
thermos.temperature = 26; // setting accepts celsius, but stores in fahrenheit
console.log(thermos.fahrenheit); // 78.8, how it is stored in fahrenheit on the class property, converted from celsius
console.log(thermos.temperature); // 26, because the getter converts back to celsius

Notice the line:

console.log(thermos.fahrenheit);

We are accessing that class prop directly. Normally we wouldn’t do that. Often we would “hide” it behind an underscore, like “_fahrenheit” to remind people that this is a private class prop. Many languages allow you to completely hide that. Traditionally JS didn’t, but you can now in the latest versions.

Look, this is a very confusing problem. I’ve always hated this problem. It doesn’t make sense why we are giving the constructor F but giving the setter C. It’s not clear why we need a getter and setter - they really aren’t needed for this implementation.

Don’t worry about it too much. The getter gets it and the setter sets it. They allow you more control. You don’t have to use them if you don’t want to.

1 Like

I feel like we’ve gone around this merry-go-round a few times. If you are still not getting this, then I might suggest seeking out some outside resources, if you want to learn it better. They might offer a different perspective. And the FCC materials are sometimes a little thin, moving over topics very quickly.

And don’t feel bad - this is hard stuff. If it was easy, high school dropouts would do it and it would pay minimum wage. There were certainly things that confused me for a while when I was learning - and now I do this for a living.

And I don’t think that understanding getter/setter patterns is crucial at this point. I worked my first job for 2 years and didn’t encounter a single getter/setter. Then I got another job and picked them up quickly.

So, it sounds like you’re getting some of the idea. Maybe take a few days off and then watch some youtube videos, etc, and see if it clicks. Maybe work on that for a while and then come back if you’re still blocked.

2 Likes