JavaScript ES6+ classes and best way to handle updating options after instantiation?

#1

Using a JS class, I would like to setup the class defaults using the constructor:

class Foo {
    constructor(options = {}) {
        this.options = options;
    }
    doSomething() => {
        return `${this.options.sound} says ${this.options.animal}`;
    }
}

Usage:

const foo = new Foo({
    sound: 'moo',
    animal: 'cow',
});
console.log(foo.doSomething());
// moo says cow

Now, let’s say later I want to use foo object again, but update it’s options … For example:

// Let’s pretend `doSomething` has code to update the object’s options:
foo.doSomething({
    sound: 'ribbit',
    animal: 'frog',
});
// ribbit says frog

I am finding that I go back and forth on this; either I new the object again
and create new instance with new options, or I re-use the same object and
write a class method to update options (like the pseudo-example immediately above).

Reasons for asking this question:

  1. I don’t really like creating new objects for utility-like modules (it just seems
    wasteful to instantiate a whole new object just to modify options).
  2. On the other hand, it seems not very clean to update the options of
    a new class after it’s been initialized (potentially error-prone).

My questions:

  • Is it best to just use new Foo(<new options>) again and create multiple instances?
  • Or, should I write a class method that update’s the current instance of Foo’s options?

Is there an ES6+ contemporary class-based pattern I can use to update options without creating a new instance? Or, should I just not worry about it and create new instances as needed?

I guess I’m curious what best practice might be in this situation?

I hope that makes some sense … Thanks in advance for reading and for the help!

0 Likes

#2

I’m just now realizing that I could also do:

const foo = new Foo({
    sound: 'moo',
    animal: 'cow',
});
foo.doSomething();
// moo says cow

foo.options = {
    sound: 'ribbit',
    animal: 'frog',
};
foo.doSomething();
// ribbit says frog

foo.options = {
    sound: 'baa',
    animal: 'sheep',
};
foo.doSomething();
// baa says sheep

Hrmm, had not considered just re-writing the object directly. Is this acceptable practice?

Mostly curious what would be best practice for the situation I present above. I want my modules to be flexible, but I also want to avoid bad practices in terms of module API.

Thanks again for listening!

0 Likes

#3

Also realizing I could use a setter, like so:

constructor(options = {}) {

  this._options = options;

}

set options(options = {}) {

  this._options = {
    ... this._options,
    ... options
  };

}

Which would allow me to keep the previous options if not overridden in the new object (and a setter would allow for a layer of validation).

Hrmm, I kinda like this approach.

I could also create a setter to update options without keeping old values (or, visa versa).

Interesting stuff… fun!

0 Likes

#4

I feel that it’s best to use multiple instances, as that obviates the need to add potentially confusing code to readjust things.

0 Likes

#5

I feel that it’s best to use multiple instances, as that obviates the need to add potentially confusing code to readjust things.

Yah, that makes a lot of sense. Keep it simple. I like it! :slight_smile:

It can be easy to get caught up in the complexities when learning new things. Thanks for the reality check. :+1:

1 Like