FAQ: Classes - Review: Classes

This community-built FAQ covers the “Review: Classes” exercise from the lesson “Classes”.

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

Web Development

Introduction To JavaScript

FAQs on the exercise Review: Classes

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

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!

Hey all, my question relates to the following code, where I’ve attempted to create a new Doctor class under the HospitalEmployee super class. Everything seems to work ok, however I also added an ‘addInsurance’ method which returns an error when invoked ‘is not a function at doctor.addInsurance’ . Does anyone know why this is the case?
class Doctor extends HospitalEmployee {
constructor(name, insurance) {
this._insurance = insurance;
get insurance() {
return this._insurance;

It looks like this._insurance is a singular value, not an array. We cannot push to a non-array object.

Oh that makes perfect sense now! Thanks Roy

1 Like

Like @laszloabonyi42094240, I added an updateInsurance method to a new Doctor subclass. I wanted to try to assign a value to the _insurance property by polling a getter get insurance, instead of using a setter. We polled getters like this in the Team Stats project, to access the arrays in _players and _games from the addPlayer and addGame methods, in order to add a new player/game using .push(). The only difference being that in Team Stats we were adding objects to arrays using .push(), whereas this time I was trying to completely reassign the _insurance property by using a reassignment operator (=).

I thought it would work, but it didn’t, and I don’t understand why. Here are the relevant parts of my code:

class HospitalEmployee {
  constructor(name) {
    this._name = name;
// etc.

class Doctor extends HospitalEmployee {
  constructor(name) {
    this._insurance = null;
  get insurance() {
    return this._insurance;
  updateInsurance(level) {
    this.insurance = level; //works if change to: this._insurance = level;
  }                         //i.e. if add underscore   ^

const doctorCalafell = new Doctor('Calafell');
doctorCalafell.updateInsurance('Level 1');

The error logged is:

TypeError: Cannot set property insurance of #<Doctor>
which has only a getter

It only works if I:

  1. access _insurance directly (as highlighted in the comment in the code above), which I obviously don’t want to do as it’s been marked as private;
  2. use a setter instead of the method updateInsurance(), as follows:
set insurance(level) {
  this._insurance = level;     //this works

doctorCalafell.insurance = 'Level 1';
console.log(doctorCalafell.insurance);   //correctly prints "Level 1"

At first, I thought it might have something to do with using null as the value initially assigned to _insurance, but it also doesn’t work if you change this to undefined, leave it empty (this._insurance;) or assign it a string. I decided to use null as I wanted to start with this field empty, and I thought null would be appropriate to indicate that the value was pending. Is this an appropriate use of null, or would undefined or leaving the property empty (this._insurance;) be better here?

Is this why?


So is it that getters can give other methods access to the private values but NOT write permission? I’m not entirely sure what write permission is, but I’d take a guess that it means permission to change or reassign a value…? So would that mean that pushing a value into an array isn’t writing because the array value itself remains unchanged (only its contents change)?..whereas to reassign the “whole” value of _insurance would require write permission, which only a setter can give… is that it?

In JS write permission is universal. We have protected variables by proxy, not by de facto.

OK… so that’s not the reason my method .updateInsurance() can’t use the getter get insurance to access the private property _insurance, and then reassign its value…

At least I attempted to find a reason :wink:

Looking forward to finding out what the actual reason is… at the moment I’m still at a loss as to why such a method can “push” to an array having accessed it via the getter, but not reassign a property’s value with the assignment operator (=) having accessed it in the same way.

We’ve been over this already.

obj = {
    _prop: [],
    get prop () {
        return this._prop;
    set prop (value) {
obj.prop = "new value"
// ['new value']

This is what has everyone’s back up that is against JS setters.

Sorry, maybe I didn’t explain my actual question very clearly…

I totally understand why the setter works in your example above, and also why using it in this way, to push a new value into a privately marked array, is controversial for some people.

In my example above, instead of adding a new value to an array, I’m actually reassigning the whole value (i.e. changing this._insurance: null to this._insurance: Level 1). As I expected, it works using a setter (obviously changing the statement from this._prop.push(value) to this._prop = value.

However, instead of using a setter, what I wanted to do was practise using the getter to access the private property (as we have been discussing here) and use a method (updateInsurance) to reassign the value. But it didn’t work, as I’ve described above, and I don’t understand why, especially after what I’ve understood by this.

Sorry, if I’m missing something obvious…

1 Like

I’ve just tried to do the same thing, but with a more simplistic version, without the added complication of parent and subclasses: and it still doesn’t work…

Works when pushing to an array:

const obj = {
  _insurance: [],
  get insurance() {
    return this._insurance
  updateInsurance(level) {
    this.insurance.push(level)     // uses getter to access _insurance

console.log(obj.insurance)       // prints "[]"   (as expected)
obj.updateInsurance('Level 1')   // calls method to add "Level 1" to array
console.log(obj.insurance)       // prints "['Level 1']"   (as expected)

Doesn’t work when reassigning entire value:

const obj = {
  _insurance: null,
  get insurance() {
    return this._insurance
  updateInsurance(level) {
    this.insurance = level      // uses getter to access _insurance

console.log(obj.insurance)      // prints "null"   (as expected)
obj.updateInsurance('Level 1')  // calls method to assign "Level 1" to _insurance
console.log(obj.insurance)      // still prints "null"   (NOT as expected)
// I expected the getter to give the method access to _insurance and
// therefore enable it to reassign the value from "null" to "Level 1"...???

You’ve discovered another nuance that maybe we haven’t touched on yet. There is a difference in values from one example the other… One’s a data structure and the other a single value. It may prove out that we cannot set a single value without a setter.

The binding to a list may be what allows other methods to append the array in a private attribute. Will have to play around and see what happens.

However, before we draw any conclusions be sure the syntax is complete. It looks like you have a missing brace in the second example (to close the method).

Update… Nope. Still null.

Yup, it needs a backing variable to work. May as well add a setter for single assignments.

obj = {
  _insurance: null,
  get insurance() {
    return this._insurance
  set insurance(level) {
    this._insurance = level;

Thanks for looking at this again :+1:
It’s good to have some expert confirmation!
Thanks for also spotting the missing curly braces (I’d missed them in both examples)… they were in my original code but got lost. I’ve updated my examples just in case someone else thinks that may be the reason…

Just one thing…
I get that you’re confirming we really need a setter for single assignments (otherwise we’d have to access the private _property directly (which is exactly what we are trying to avoid)…
but… what do you mean by “backing variable”?

I guess this is a good argument to support those in favour of setters! :smiley:

1 Like

It does bolster the argument for using them for assignment, and not using them for pushing.


Basically, it is the private attribute, where obj.prop is the public alias that invokes the getter.


This nuance makes me ponder whether there is something analogous to the difference between a const and a let or var, in terms of using those to store objects and arrays.

If we store objects and arrays in a let or var, then we can re-assign the array or object whole. But if we store them in a const, we can’t; but we can still fully manipulate their array elements and object key:value pairs.

What is ‘protected’ by the const is re-assigning to the const itself, but it doesn’t prevent us from manipulating an object (data structure) stored inside one.

Is this what’s going on here?
So in essence… it seems like the const's reference is ‘write-protected’.

And in the object.property scenario, with only a getter but no setter, then so too it seems the property's reference is ‘write-protected’ (directly contravening _convention aside).

The presence of the getter similarly allows us to manipulate the data inside the referenced data structure, but not to change the reference itself.

For that we need a setter.

This was a useful analogy in my own head… so thought I would share.

p.s. Roy can perform mild janitorial duties / full open-heart surgery on my terminology as deemed necessary :smile:

An array or object are values that reference other values. While we cannot alter its value (if set as a constant), we can still alter the values it references. const is permanent for the session.

Tip: When working in the JS console, don’t use const or let or you have restart the session and lose all your work if you need to correct something. When you get the bugs ironed out or theory proved out, then in the saved code add in the appropriate keywords as apply.

Properties are in no way similar to constants, since they are not actually ‘write protected’ if we know how to access them. Objects are mutable to the point where we can even remove attributes.

For clarification:

I do state at that outset that I found these two scenarios to be analogous; I’m not making any claim here of a direct technical equivalence.

If we are going to be good developers and good troubleshooters, then we need all our problem-solving skills at the ready; and not restrict ourselves to swallowing technical terminology by rote.

For sub-clarification:
Particularly as a beginner, understanding the technical definitions is important. However, ultimately a real depth of understanding will come from your own thinking as you gain more knowledge and are able to relate concepts to other concepts which you already grasp.

Or: how the brain works.

If you don’t trust in it to make its own leaps, you won’t make a developer; once the syntax falls into the background, it’s you and your brain.

Not sure what analogy you wish to draw, here. Variable declaration keywords and object properties/methods are worlds apart.

Scenario 1
Const: Cannot be re-assigned. But stored objects and arrays remain mutable.

Scenario 2
Object._property with a getter but no setter: Adhering to convention, the property cannot be re-assigned. But stored objects and arrays remain mutable.

Therein lies the similarity: an analogous situation. The upshot is the same, but I’m not making a claim of technical equivalence between the two language features.

And so this is a matter of reasoning :thinking:, not one of technical correctness :nerd_face:

As a directive to other developers, the property should not be re-assigned. There is no write protection and nothing analogous with const.

When a developer sees a property written as a backing variable, they know to look for and refer to, at the very least a getter. If the value is a data structure then expect to see addSomething methods, or a setter method that pushes to or updates the data structure, and even weirder syntax at the caller end.

this.appetizers = dish;

This is all to protect the data as much as we can, which is to say, as much as we can. Short of a database, that is the best we can do; we hint to other programmers to acknowledge this need for protection and hope they will follow a regimen that won’t encroach.

The full quote was:

Appreciate we are on a FAQ page, but I was engaging in intellectually honest discussion, and the above chopping up of a quote in order to provide correction is not in keeping.

The statement is obviously true. By choice and not by built-in restriction, but a truthy statement nonetheless.


Are a mental tool for transferring meaning (not exacting likeness, which wouldn’t be analogy) from one concept or subject to another. Yes you can even do this with whole different subjects!

Let’s see what wikipedia has got to say about the analogy:

It has been argued that analogy is “the core of cognition”.

A powerful tool for learning, then.

So if an analogy is helpful to someone to take on board a new concept, then that strengthens their understanding. That’s down to the individual learner and for nobody else to impose upon either way.

One can agree or disagree with someone’s reasoning; but that’s just opinion.

1 Like