FAQ: Advanced Objects - Setters

This community-built FAQ covers the “Setters” exercise from the lesson “Advanced Objects”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Web Development

Introduction To JavaScript

FAQs on the exercise Setters

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

The last task of the Setters section reads:
To check that the setter method worked, console.log() robot.numOfSensors .

This doesn’t make sense to me. Shouldn’t we be checking that _numOfSensors was updated with the setter?
also, if I am wrong, is robot.numOfSensors calling the getter or the setter? Since both the getter and setter have the same name, I’m not sure what is being called here.

1 Like

get and set are special keywords that behave like properties, the name of which is the same for both because they both relate to the same backing variable (the one with the underscore prefix). We cannot call them directly because they are engaged in the background.

Above we must assume that the value has already been set, and we’re only polling the variable for its current value. When we write,

console.log(robot.property);

we are accessing the getter, which then returns the backing variable value the same way a typical object would, and when we write,

robot.property = "some value";

we are accessing the setter, but it depends upon the getter for some special binding which I don’t really understand well enough to explain but if you can handle dry technical reading, I recommend digging deeper into the relationship, and why setters depend upon getters in the first place. We can’t have set without get for the variable in question.

1 Like

Yes! I get it now. Thank you @mtf!

1 Like

You’re welcome.

Aside

One thing you don’t want to do is create a circular reference. Consider the following code…

class Robot {
    constructor(foo, bar) {
        this._foo = foo;
        this._bar = bar;
    }
    get foo() {
        return this._foo;
    }
    set foo(x) {
        this.foo = x;
    }
    get bar() {
        return this._bar;
    }
    set bar(x) {
        this.bar = x;
    }
}

Notice how the setters are calling the getter, not the backing variable? That conflicts with what’s already going on in the background and pushes all the calls to a stack. The browser steps in and stops it eventually.

Uncaught RangeError: Maximum call stack size exceeded

That’s what we would call a fatal error. Keep this in mind going forward so you never make this mistake.

Bottom line, we cannot set and get a variable at the same time. Only set or get.

1 Like

Good to know . Thanks!

1 Like

I’m stuck on step two, I’ve added the setter, and the console is not giving me any errors. However, the system is telling me I’m still making a mistake, can someone please advise?

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 >= 0) {
      this.__numOfSensors = num;
    }
  }
};

the line after your if statement…this.__numOfSensors instead of this._numOfSensors

the example logs the one with underscore also console.log(person._age);

When I complete the final task on this exercise console.log(robot.numOfSensors);, I note that if you assign robot.numOfSensors as a string instead of a number, it logs the expected message followed by the previous _numOfSensors value:

Pass in a number that is greater than or equal to 0
15

Is this correct? I understand why _numOfSensors is unchanged, but I don’t understand the code is returning it.

This line uses the getter to return _numOfSensors.

1 Like

Ah. So the variable num that’s passed in the setter is invalidated by the setter as it’s not a number, however the variable _numOfSensors is already present and correct for the getter to reference, so it returns console.log from both the getter and the setter (whereas if the setter passed the if statement as true, it would only reassign the _numOfSensors variable and nothing would be logged to the console.) Think I’ve got it. Thanks!

1 Like

There is a thing, that I dont understand:

if the codeline reads:
robot.numOfSensors = 100;
the output ist: 100

if the codeline reads:
robot.numOfSensors = “something”;
the output is: Pass in a number that is greater than or equal to 0

but if the codeline is:
robot.numOfSensors = 100a;
it produces an error (SyntaxError: Unexpected identifier)

My question is, how does javascript consider “100a”, if it is not in brackets that mark it as a string? I have the feeling, that I did not understand some basic conception.

Anything that is not in quotes is regarded as an identifier. 100 is a number, but a is not. JS sees this as an unexpected identifier.

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 >= 0) {
this._numOfSensors = num;
} else {
return ‘Pass in a number that is greater than or equal to 0’
}
}
};

robot.numOfSensors = ‘dfdd’

console.log(robot.numOfSensors)

HUH ?

Why does this return 15 ?

should it not return : Pass in a number that is greater than or equal to 0

Because the value remains unchanged due to incorrect inputs. The setter should have raised the error message. We don’t need to test inside the getter, just return the value.

get numSensors () {
    return this._numSensors;
}

I don’t understand. If its incorrect inputs why is it not then returning the else value ?

should it not return either : ‘Sensors are currently down.’ from the getter or ‘Pass in a number that is greater than or equal to 0’ from the setter?

The error message should behave as expected in the setter. There is no need for any message in the getter. Just return the value.

If you wish to return a message from the getter when the value is 0,

return this._numSensors ? this._numSensors : "Sensors are down";

Zero is falsy to will revert to the default in the third expression of the ternary.

Correct :smiley:

Yes…the setter wouldn’t log anything to the console, but instead the getter now logs the reassigned value (100) when we call it with console.log(robot.numOfSensors)

Thanks for that example using the string '100' instead of the number. I worked it through and it helps to see and understand what the getter and setter are doing :sweat_smile: :muscle: