School Catalogue - numberOfStudents not working

The problem in question is: https://www.codecademy.com/courses/introduction-to-javascript/projects/school-catalog

class School {
  constructor(name, level, numberOfStudents) {
    this._name = name;
    this._level = [];
    this._numberOfStudents = numberOfStudents;
  }
  
  get name() {
    return this._name;
  }
  
  get level() {
    return this._level;
  }
  
  get numberOfStudents() {
    return this._numberOfStudents;
  }
  
  set numberOfStudents(value) {
    if (value.isNaN()) {
      console.log('Invalid input: numberOfStudents must be set to a Number.')
    } else {
      //this._numberOfStudents = value;
          this._numberOfStudents = 5;
    }
  }
  
  quickFacts() {
    console.log(`${this.name} educates ${this.numberOfStudents} students at the ${this.level} school level.`)
  }
  
  static pickSubstituteTeacher(substituteTeachers) {
    const randomIndex = Math.floor(substituteTeachers.length * Math.random());
    return substituteTeachers[randomIndex];
  }
}

class PrimarySchool extends School {
  constructor(name, numberOfStudents, pickupPolicy) {
    super(name, 'primary', numberOfStudents);
    this._pickupPolicy = pickupPolicy;
  }
  
  get pickupPolicy() {
    return this._pickupPolicy
  }
}

class HighSchool extends School {
  constructor(name, numberOfStudents, sportsTeams) {
    super(name, 'high', numberOfStudents);
    this._sportsTeams = sportsTeams;
  }
  
  get sportsTeams() {
    return this._sportsTeams;
    console.log(sportsTeams);
  }
}

const lorraineHansbury = new PrimarySchool('Lorraine Hansbury', 'test', 'Students must be picked up by a parent, guardian, or a family member over the age of 13.')
lorraineHansbury.quickFacts();
School.pickSubstituteTeacher('Jamal Crawford', 'Lou Williams', 'J. R. Smith', 'James Harden', 'Jason Terry', 'Manu Ginobli');
const alSmith = new HighSchool('Al E. Smith', 415, ['Baseball', 'Basketball', 'Volleyball', 'Track and Field']);
alSmith.quickFacts();
console.log(alSmith.sportsTeams);

Why numberOfStudents does not work.

Hey @radekkw, welcome to the forums!

Hmmm, what is the result you are trying to get? This is the result I get when I run your code:

image

Thanks for the quick reply :slight_smile:
I expect 5 instead of 415.
If I uncomment (this._numberOfStudents = value;) then I expect: console.log(‘Invalid input: numberOfStudents must be set to a Number.’)
How to check if numberOfStudents is executing code?

Hello, @radekkw.

console.log() statements are a good way to observe what is or isn’t happening. If you’re not sure where the control flow is going add statements like these:

const someFunction = someParam => {
  console.log("someFunction")
  // do stuff
  return something // maybe?
}

const someOtherFunction = (param1, param2) => {
  console.log("someOtherFunction")
  // do stuff to get a value
  console.log(value) // is the value what I was expecting?
  return something // maybe?
}

Now when the code executes, I’ll either see or not see the names of the functions printed to the console. You can add as many as you need to in order to see values you are expecting, etc. When you’re finished debugging, delete them.

Thanks, I always do that.
The thing is, the code numberOfStudents is never executed. Why?

Short answer: it’s never called. Consider what happens when you instantiate a new School object. When & where is the _numberOfStudnts property assigned a value?
numberOfStudents(value) is a setter method. How would/could you use it instead of what is currently being used?

Question: Should isNaN() be a method or a function?

This is a piece of code from the official video guide from CoceCademy

I do not understand. What does this code (numberOfStudents) do?
I expect 5 instead of 415.
If I uncomment (this._numberOfStudents = value;) then I expect: console.log(‘Invalid input: numberOfStudents must be set to a Number.’)

Currently, the setter is not called/invoked when you instantiate a new School object. The ._numberOfStudents value is assigned inside the constructor method of the School class. If you wanted to use the setter method instead of the parent class’ constructor in order to validate the input, there are a few changes you’d need to make. Consider what super does. What if you didn’t include numberOfStudents (the parameter) in the call to super? How could you use the setter instead?

Ah, okay. It was added in ES6 to get around NaN.

https://medium.com/dailyjs/better-nan-check-with-es6-number-isnan-517861d32be3

So actually this piece of code is not needed there.
It is a pity that in this lesson ( School Catalogue) there is no answer (explanation) to these issues.

I suppose it’s not needed if it isn’t used, but you can make use of it if you choose to do so. Try this:

class PrimarySchool extends School {
  constructor(name, num, pickupPolicy) { // I changed the parameter to num for clarity
    super(name, 'primary'); // don't send num to the parent constructor
    this.numberOfStudents = num; // invoke the setter method
    this._pickupPolicy = pickupPolicy;
  }

Note: in the setter you’re going to throw an error due to incorrect use of isNaN. Should be isNaN(value).

1 Like

See my comment above. The method is the preferred approach.

2 Likes

Thanks for the help.
Now it works, it is executed: numberOfStudents.

Anyway, there is a slight mistake in the official CoceCademy video: isNaN().

How to get console.log(‘Invalid input: numberOfStudents must be set to a Number.’)?

Here is the last part of the article that @mtf linked to :

Conclusion

When checking if a value is equal to NaN . Use the Number.isNaN method. Do NOT use isNaN :nerd_face:

We aren’t actually checking for the specific value, NaN. We only want to know if the input value is numeric or not, so isNaN(value) is not only suitable, but preferable in my opinion. That way your value of test will result in the message being printed.

2 Likes

Using anything named isNaN to test type offends me >.>

To be completely honest though, it looks like isNaN is completely reasonable. It just gives you a false when it is a number, which makes sense because the JavaScript Founders were obviously English majors.

NaN is a specific value that a floating point number can have, it’s got nothing to do with types. NaN is float. Period.

Ah. So, typeof value != 'number' would be better ?

Actually, to be more thorough, I may still be missing an edge case or few, this would be better:

  set numberOfStudents(value) {
    if (typeof value != 'number' || value != Math.floor(value) || value < 0) {
      console.log('Invalid input: numberOfStudents must be set to a whole number greater than zero.')
    } else {
      this._numberOfStudents = value;
    }
  }
2 Likes