1

I want it to be the case that when I instantiate an instance of the class TableCategory, an object is created using the data passed in at instantiation. I want this to happen automatically at instantiation. I don't want have to instantiate the class and then call a method that creates the object. This seems unnecessary cumbersome.

I am using a class because I then want to manipulate the resultant object using getters and setters for multiple instantiations. (In case you wonder why I'm not just using an object in the first place.)

I'm not 100% clear on classes in JS so I'm not sure where I'm going wrong. Please note the object creation is a the product of a function it takes an array passed in at instantiation and an array that is native to the class.

Here's my class:

export class TableCategory {
  constructor(categoryValues = []) {
    this.categoryValues = categoryValues;
    this.categoryKeys = ['alpha','beta','gamma', 'delta'];
    this.categoryData = this.categoryKeys.forEach(function(key, i) { 
      return this.categoryData[key] = this.categoryValues[i]; 
     });
   }
}


Then, for example:

const foo = new TableCategory(['a'. 'b', 'c', 'd']);
console.log(foo.categoryData.beta); // b

Perhaps I need to use static ? Not sure, grateful for any help

4
  • Why would you store redundant data? If you have the categoryData (after fixing your code), then why you still need the other two properties? They are easy to get with Object.keys, Object.values from the third property. You'll have unnecessary overhead to keep those properties synchronised when you start mutating an instance. Commented Mar 3, 2021 at 16:28
  • @trincot I don't see what is redundant. Could you clarify? Commented Mar 3, 2021 at 16:33
  • Oh, because the object's values will be different with each instantiation, but the keys are always going to be the same. Otherwise I would have to pass in two arrays with every instantiation, and one will always be the same. But maybe I misunderstand you? Commented Mar 3, 2021 at 16:37
  • OK, I have posted an answer that shows an alternative implementation. categoryData will have all key/value pairs, but those keys are also in categoryKeys, and the values are also in categoryValues, so you have everything in double. I think you only need categoryData, as the rest is implied by it. If then you mutate and change a value later, you don't have to change it both in categoryData and in categoryValues (to avoid inconsistency). Commented Mar 3, 2021 at 16:47

2 Answers 2

1

forEach() doesn't return anything. Create an empty categoryData object, and then fill it in in the forEach loop.

Also, you need to use an arrow function to be able to access this in the callback function.

class TableCategory {
  constructor(categoryValues = []) {
    this.categoryValues = categoryValues;
    this.categoryKeys = ['alpha', 'beta', 'gamma', 'delta'];
    this.categoryData = {};
    this.categoryKeys.forEach((key, i) =>
      this.categoryData[key] = this.categoryValues[i]
    )
  }
}

const foo = new TableCategory(['a', 'b', 'c', 'd']);
console.log(foo.categoryData.beta); // b

Sign up to request clarification or add additional context in comments.

Comments

1

forEach does not return anything else than undefined. You can still get the desired object in a functional way, but with Object.fromEntries.

Also, as you say you use a class because you intend to mutate the instance(s) with getters and setters, I don't think it is a good idea to still store the values and keys separately from the third property, which has all key/value information.

You could for instance do this:

class TableCategory {
  constructor(values = []) {
    this._obj = Object.fromEntries(['alpha','beta','gamma', 'delta']
                      .map((key, i) => [key, values[i]]));
  }
  get values() {
      return Object.values(this._obj);
  }
  get keys() {
      return Object.keys(this._obj);
  }
}

let obj = new TableCategory(["this", "is", "a", "test"]);

console.log(obj.values);

2 Comments

Thank you, this is very clean. I'm not that experienced with JS so forgive me, but: would this still enable me to update a specific value, i.e. using your instance, obj.values.beta = 'new value'; Given the functional approach you provide perhaps it would be better to generate a new object when I need to update the data rather than attempt mutate a specific value.
No you would write getters and setters that would act directly on the property, which I named _obj.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.