0

I'm kinda new with js + ES6 + class; I have problem with creating function inside constructor.

#1. I need to add new Hobby, a person allowed to have plenty hobbies ;
#2. I don't know how to show all the data of students;

another questions are in the comments ,in case if you want to answer it too, if not i'm also fine. so here's my code :

class Student {
  constructor(name,hobbies){

    this.name = name;

    var hobby = new Set(); //do I set here or inside the function ??
 //since the function addHobbies also need, then it's fine to be global right ?


    this.hobbies = (hobbies) => {    //function ES6 like this right ??

      this.hobbies = hobby.add(hobbies);

      return this.hobbies;  //can I return hobby instead of this.hobbies ??
    };
  }
  setName(newName){
    this.name = newName;
  }

  addHobbies(newHobbies){
    this.Hobbies = hobby.add(newHobbies); //it should be like this to add >> to set ?
  }


  getName(){
    return this.name;
  }

  getHobbies(){
    return this.hobbies;
  }
}

and how to return all the data ?

let andy = new Student("andy","dance");
let vince = new Student("vince","codding");

so it will show all students-attribute by getCode() ?

Dell Watson
  • 367
  • 1
  • 3
  • 13
  • `return this.hobbies` will simply return the function, so that doesn't make sense to do. `hobby.add(newHobbies);` won't work since `hobby` doesn't exist in that scope. – Felix Kling Dec 07 '16 at 08:15
  • @FelixKling well I did try to declare hobby inside function before this, didnt work like i want tho. – Dell Watson Dec 07 '16 at 08:20

3 Answers3

1

Try this:

class Student {
  constructor(name, hobbies) {
    this.name = name;

    // Allow passing both an array of hobbies and a single hobby
    this.hobbies = Array.isArray(hobbies) ? new Set(hobbies) : new Set([hobbies]);
  }

  setName(newName) {
    this.name = newName;
  }

  addHobbies(newHobbies) {
      if (Array.isArray(newHobbies)) {
          newHobbies.forEach((hobby) => this.hobbies.add(hobby));
      } else {
          this.hobbies.add(newHobbies);
      }
  }

  getName() {
    return this.name;
  }

  getHobbies() {
    return this.hobbies;
  }
}

let andy = new Student("andy","dancing");
let vince = new Student("vince",["codding", "running"]);
andy.addHobbies("slipping");
vince.addHobbies(["running", "eating"]);
Shai
  • 3,659
  • 2
  • 13
  • 26
  • This is JavaScript. There is no `private` keyword or any member declarations. – Bergi Dec 07 '16 at 08:38
  • Only one thing is it is better to have one type for `this.hobbies`. I mean in constructor you have to create an array of one element or even a Set to have them unique – ZedXter Dec 07 '16 at 08:39
  • @Bergi You're right, I use TypeScript myself and took it from there. I revised my answer. Thanks! – Shai Dec 07 '16 at 08:56
1

do I set here or inside the function ??

That depends on what you need. Do you want each Student instead to have one set of hobbies, or do you want to create a new set every time the function is called?

this.hobbies = (hobbies) => {    //function ES6 like this right ??
    this.hobbies = hobby.add(hobbies);

That doesn't work at all. You're creating the property with a function value, but when the method is called you're overwriting the property with the return value of the add method.


To make it work, I'd recommend making the .hobbies set an instance property instead of a local variable.

class Student {
  constructor(name, ...hobbies) {
    this.name = name;
    this.hobbies = new Set();
    this.addHobbies(...hobbies);
  }

  getName() {
    return this.name;
  }
  setName(newName) {
    this.name = newName;
  }

  getHobbies() {
    return this.hobbies;
  }
  addHobbies(...newHobbies) {
    for (const newHobby of newHobbies)
      this.hobbies.add(newHobby);
  }
}

Alternatively, if you insist on using a local constructor variable, it would look like this:

class Student {
  constructor(name, ...hobbies) {
    this.name = name;
    this.hobbies = new Set(...hobbies);

    this.getHobbies = () => {
      return this.hobbies;
    };
    this.addHobbies = (...newHobbies) => {
      for (const newHobby of newHobbies)
        this.hobbies.add(newHobby);
    };
  }

  … // further methods (for name etc)
}
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

You are in the correct direction. I have rewritten your class to do what I think is more similar to what you are trying to achieve.

Play with the code at: https://jsbin.com/vejumo/edit?js,console

And here's the rewritten class:

class Student {
  constructor(name, hobbies = []){

    this.name = name;

    // new Set() is used to work with objects. It does not work with well with strings
    // Let's use an array to store the hobbies.
    // if a hobby or an hobbies array is passed, store it, otherwise set an empty array.
    this.hobbies = this.parseHobbies(hobbies); 
  }

  // This function will normalize the hobbies to an Array
  parseHobbies(hobbies) {
    if (typeof hobbies === "string") {
      // hobbies is a string, means it's a single hobby and not an array
      return [hobbies];
    }
    // Assuming the hobbies is a an Array
    return hobbies; 
  }

  setName(newName) {
    this.name = newName;
  }

  // this function will allow you to add a single hobby to the array
  addHobbies(hobbies = []) {
    // Same logic like in constract, this can accept a string or an array
    // We use Array.concat and push to append to array
    this.hobbies = this.hobbies.concat(this.parseHobbies(hobbies)); 
  }

  getName() {
    return this.name;
  }

  getHobbies() {
    return this.hobbies
  }

  // This will return all student attributes.
  getAttributes() {
    // Return a copy of all the attributes instead of returning references
    return Object.assign({}, this);
  }
}

let george = new Student("George", "Sports");
george.addHobbies(["Singing", "Fishing"]);
george.addHobbies("Dancing");
console.log(george.getAttributes());
aaa
  • 601
  • 6
  • 13