Search code examples
javascriptobjectmethodschainingoptimal

JavaScript how to create method working similar with many properties without code repeating?


I want to create an object with properties and some properties need to be treated with two similar methods, how to make it optimal without reapeting the code? Here is the example of the object it seems it suppose to be the way to make it much easier way .. Any suggestions?!

const points =  {
    sum : 10,
    offense : 0,
    defense: 0,
    support: 0,

    addOffense(){
        if (this.sum > 0) {
            this.sum--;
            this.offense++;
        }
        return this;
    },
    subtractOffense(){ 
        if (this.offense > 0) {
            this.offense--;
            this.sum++;
        }
        return this;
    },
    addDefense(){
        if (this.sum > 0) {
            this.sum--;
            this.offense++;
        }
        return this;
    },
    subtractDefense(){ 
        if (this.offense > 0) {
            this.offense--;
            this.sum++;
        }
        return this;
    },
    addSupport(){
        if (this.sum > 0) {
            this.sum--;
            this.offense++;
        }
        return this;
    },
    subtractSupport(){ 
        if (this.offense > 0) {
            this.offense--;
            this.sum++;
        }
        return this;
    }
}

console.log(points.addOffense().offense)

I want to make just 2 methods instead of repeated 6 but how to pass properly property what I want to work with to the method and how to work with them outside?! If you have an idea how to do that, please, with code examples ... because really want to understand the right syntax as well!


Solution

  • Utilize dynamic property names to consolidate the similar logic. Consider having just an add and subtract method, which takes an argument - either offense, defense, or support. Validate that the argument is one of those permitted props, then validate that the points are available to either add or subtract, then you can use bracket notation to add and subtract from the sum and from the dynamic prop.

    const points =  {
        sum : 10,
        offense : 0,
        defense: 0,
        support: 0,
        validate(prop) {
          // A type-aware system would be better than this, if possible
          if (prop !== 'offense' && prop !== 'defense' && prop !== 'support') {
            throw new Error('Invalid prop');
          }
        },
        subtract(prop) {
          this.validate(prop);
          if (this[prop] === 0) {
            // no change; at minimum
            return this;
          }
          this[prop] -= 1;
          this.sum += 1;
          return this;
        },
        add(prop) {
          this.validate(prop);
          if (this.sum === 0) {
            // no change; can't remove from sum any more
            return this;
          }
          this[prop] += 1;
          this.sum -= 1;
          return this;
        }
    };
    const result = points
      .add('offense') // 1
      .add('offense')
      .add('offense')
      .add('offense')
      .add('offense')
      .add('offense')
      .add('offense') // 7
      .subtract('offense')
      .subtract('offense') // 5
      .add('offense')
      .add('offense')
      .add('offense')
      .add('offense')
      .add('offense') // 10
      .add('defense') // past sum
    console.log(result);