Search code examples
javascriptjquerygetter-setter

How to write a global get+set method for object


My question is easy to understand, I have an object (or class), and I want to have ONE method which can getting AND setting a property.

In fact, I have no problem to write it for "simple" properties. It becomes difficult when my class has object properties, and that I want to access or alter a nested one.

My class:

var MyClass = function() {
    this.name = 'defaultName';

    this.list = {
        a: 1,
        b: 6
    };
}

Simple class, isn't it? Then, what I write for my method:

MyClass.prototype.getset = function(prop) {
    let value = arguments[1];
    let path = prop.split('.');

    prop = this;

    $(path).each(function(i) { prop = prop[this]; }

    if (value) {
        prop = value;
        return this;
    }

    return prop;
}

The "get part" works (MyClass.getset('list.b') returns 6). But the "set part"... does not work.

I want that when I execute MyClass.getset('list.b', 2), the b property of list becomes 2, and that's not the case.

I know why my version is not working (my prop variable is just a "copy" and does not affect the object itself), but I can't find solution for this...

Thanks for you help!


Solution

  • If you're assigning a primitive, you need to assign to a property of an object for the object to be changed as well. Check if value, and if so, navigate to and change from the next to last property, rather than the final property. Use reduce for brevity:

    var MyClass = function() {
      this.name = 'defaultName';
    
      this.list = {
        a: 1,
        b: 6
      };
    }
    
    MyClass.prototype.getset = function(prop, value) {
      const props = prop.split('.');
      const lastProp = props.pop();
      const lastObj = props.reduce((obj, prop) => obj[prop], this);
      if (value) {
        lastObj[lastProp] = value;
        return this;
      } else return lastObj[lastProp];
    }
    
    const mc = new MyClass();
    mc.getset('list.b', 2);
    console.log(mc.list.b);
    console.log(mc.getset('list.b'));