2

This is my base object:

let resources = {
    TEST_FLAG: false,
    FRUIT: 'banana',
    ID: 11
};

I would like to access each property of that object through a setter and a getter. I attempt to do that below:

let dynamicResources = resources

for (let key in resources) {
    Object.defineProperty(dynamicResources, key, {
        get() {
            console.log(`[debug]: GET <${key}>, VALUE <${this[key]}>`);
            return `${this[key]}`;
        },

        set(value) {
            console.log(`[debug]: SET <${key}>, VALUE <${this[key]}>`);
            this[key] = value;
        }
    });
}

The idea is that the getter and setter can be generated from a base object with arbitrary number of properties.

When I console.log() the resulting object I get this:

{
  TEST_FLAG: [Getter/Setter],
  FRUIT: [Getter/Setter],
  ID: [Getter/Setter]
}

Which is an indication that the factory loop has worked. However, when I do this:

dynamicResources.FRUIT = 'berry';

I get the following error:

  set: function set(value) {
  RangeError: Maximum call stack size exceeded

which is an indication that the nested functions are somewhat malformed.

How can I generate a dynamic getter/setter object based on a generic base object?

7
  • 1
    You got an infinite recursion, the this[key] = value statement from the setter calls the setter function again. To fix that, store and retrieve the value to/from a different property. Commented Feb 14, 2020 at 0:21
  • As @Titus said you're not really grasping the concept of getters and setters in JS. You need a separate property that contains the value. All getters and setters are just proxies. Commented Feb 14, 2020 at 0:24
  • Can you tell us what your ultimate goal is? It can't be creating console logs, right? Maybe there's a different way to reach that goal. Commented Feb 14, 2020 at 0:26
  • The goal is to be able to set and get values using just property names, such as foo.ID = 33, foo.FRUIT = 'orange', foo.TEST_FLAG = false. Commented Feb 14, 2020 at 0:29
  • But instead of manually defining the individual setter and getter access points, I would like to generate them with a factory function. So if there are other properties, those will have setter and getter functionality as well. Commented Feb 14, 2020 at 0:31

2 Answers 2

6

Use Proxy constructor. Look to Developer Mozilla Proxy Page

var dynamicObject = new Proxy({
   TEST_FLAG: false,
   FRUIT: 'banana',
   ID: 11
  },{
  get:function(target,key){
   console.log(`get ${key} value. value is: ${target[key]}`);
   return target[key]
  },
  set:function(target,key,val){
    console.log(`set ${key} value. old value is:${target[key]} new value is ${val}`)
    target[key] = val;
    return true;
  }
})

console.log(dynamicObject.ID);
dynamicObject.ID = 25;




// Output is:
/*
get ID value. value is: 11
11
set ID value. old value is:11 new value is 25
*/

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

1 Comment

Is it possible to have a method inside the Proxy, a method that is also will be callable, for example: dynamicResources.lock(true)?
4

Try like this:

let resources = {
    TEST_FLAG: false,
    FRUIT: 'banana',
    ID: 11
};

let dynamicResources = {
    _state: {...resources}
}

for (let key in resources) {
    Object.defineProperty(dynamicResources, key, {
        get() {
            const internalKey = key
            return this._state[internalKey]
        },
        set(value) {
            const internalKey = key
            this._state[internalKey] = value;
        }
    });
}
console.log(dynamicResources.FRUIT)
dynamicResources.FRUIT = 'berry';
console.log(dynamicResources.FRUIT)

Comments

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.