Why do I need a setter, if I am using _ to not have the property changed by others?

Question

If I am using _ to make sure other developers know to not actively change the value of a property, why do I need a setter?

Answer

When we decide to implement setters, it is because even though we used the underscore to visually alert other developers that the property must not be changed directly, we plan to use that property dynamically (aka, we want to have it’s value changed) through the setter to modify its value indirectly and under our own conditions, that way we can make sure there is always a value being assign(not an empty value like null or an empty string), and/or it is of the type we need (ie. string). In short, we give “privatized” properties (because they are only private by developer’s code of honor, not because of JavaScript as you may recap from here) a setter when we want them to be modified in such way that we can prevent unnecessary or unexpected errors.

To clarify, let’s adjust the robot object as an example:

const robot = {
  _model: '1E78V2',
  _energyLevel: 100,
  //lets give it a energy level getter
  get energyLevel () {
    return this._energyLevel;
  }
//and since we want to have the energy level to be modified as the robot 
//performs different tasks, we will give it a setter:
  set energyLevel(numLevel) {
    if( numLevel && typeof numLevel === "Number" && numLevel > 0 ){
    // we check first if the argument is true (aka if a value has been given), and if its type is a number, and if the value is greater than 0. If all that is true, then:
      this._energyLevel = numLevel;
    } else {
      console.log( 'Error:  Value does not exist, is not a number, or not greater than zero' );
   }
  }
  
};

with that setter we can interact with the energy level, making sure that it is under our conditions. So, as we can see, some of the properties that we don’t want to have directly changed, we do intend to use them as mutable properties (having their values change), but we use setters as safety measure so they can be modifed under the conditions that we want.

15 Likes

When numLevel is zero, the first operand will yield false.

9 Likes

Thanks for catching it! Edited.

4 Likes

It will still be false when numLevel is zero. It would appear that (first) operand is not needed.

7 Likes

Hey there!

if( numLevel && typeof numLevel === "Number" && numLevel > 0 )

As far as I understand if we pass 0 as the numLevel it will be false since it zero also means a boolean false right? So we don’t need to use the first operand.

Also if we don’t give a value to the numLevel it will return undefined and we check that with :

numLevel === “Number”

Right?

1 Like

Yes, it is redundant given the final operand checks for positive, non-zero.

Will be false if undefined.

4 Likes

2 posts were split to a new topic: Underscore naming convention

Hi Alex, thanks for the simplistic explanation. It really clears the concept of how setters can help manipulate values based upon certain conditions.

1 Like

why normal methods can’t be used for this purpose? what is their deficiency and what is the necessity of creation setter (also getter) methods?

1 Like

let a=0;
console.log(typeof a);

This is giving result as number instead of boolean.

Why would we expect a boolean?

ADVANCED OBJECTS > Setters exercise

const robot = {
  _model: '1E78V2',
  _energyLevel: 100,
  _numOfSensors: 15,
  get numOfSensors(){
    if(typeof this._numOfSensors === 'number'){
      return this._numOfSensors;
    } else {
      return 'Sensors are currently down.'
    }
  },
  set numOfSensors (num) {
    if(typeof num === 'Number' && num >= 10){
      //num is set to greater than 10
      return this._numOfSensors = num;
    } else {
      return 'Pass in a number that is greater than or equal to 0'
    }
  }
};

robot.numOfSensors = 7;
console.log(robot.numOfSensors);
//gives out 15 from _numOfSensors

In the setter (if statement check), I’ve put the condition that the number should be greater than 10. I had an impression that if I set the value less than 10, it’ll return the else statement (from setter method) since the condition is false.
But it turns out, it doesn’t take the value and outputs value from _numOfSensors.
Can anybody provide an insight into what am I missing to understand?

The nomenclature is specific.

num instanceof Number

vs.

typeof num === 'number'

Thank you for replying.
But I’m sorry, I’m not so clear still - May be because I’m new to all these and still learning.

How can I set it to show else statement when the number less than 10 is passed?

Is your setter throwing an error?

My understanding is that the functionality of typeof will will return specific literal strings(i.e. string, number, boolean and undefined) and the case of the string matters so JavaScript will only act on the check if you write it using lowercase. By using ‘Number’ you are asking Javascript to return something on a string it isn’t designed to do. So like mtf kind of talked about,but, didn’t answer you question directly(I guess he wanted to enter a socratic dialogue with you and have you figure it out) you simply needed to change your code there to a lower case ‘N’(i.e.number) and you code would work to filter out numbers less than 10 as the numbers that will trigger the else return text. Here is link to an explanation at MDN(The Mozilla folks) that will hopefully help in understanding this Click here for explanation of typof. I am only answering because the conversation looked like it died and wanted to help future readers of this forum thread

1 Like