Search code examples
javascriptproxyecmascript-6es6-proxy

Javascript ES6 Proxy


I need to create an object that stores another objects. Each property of the big object has two properties 'value' and 'callback'.

let bigObj = {
    first: {
        value: true,
        callback: () => {}
    },
    second: {
        value: false,
        callback: () => {}
    }, {...}
}

I want to be able to get and change the value property by using bigObj.first / bigObj.first = "false", and the callback.. through the classic method: bigObj.first.callback = () => {}.

Each time the property 'value' is changed, I want to call its callback function.

Here's what I did

var proxy = new Proxy({
    first: {
        value: true,
        callback: () => {}
    }
}, {
    get(target, key) {
        return key in target ? target[key].value : null;
    },
    set(target, key, value) {
        target[key] ? target[key].value = value : target[key] = {value, callback: () => {}};
        key !== 'callback' && target[key].callback();
        return true;
    }
});

The problem is that I can not change the callback property.

proxy.first.callback = () => console.log('new cb'); // won't do anything.

Do you have any ideas on how I could change the code so it would work?

Thank you.


Solution

  • The way you have it set up, proxy.first is returning a boolean. So then proxy.first.callback = ends up being false.callback = or true.callback =. These at least don't throw exceptions, but they're useless. If the value was an object instead of a boolean, you could make the value itself be a proxy, but you can't create a proxy with a non-object as the target.

    Another option would be to have a special value with which you set first, that tells it to insert the callback. Below is an example, where if you pass in an object like {callback: () => {}}, then it will insert that as the callback. But anything else it will get set as the value.

    var proxy = new Proxy({
        first: {
            value: true,
            callback: () => {}
        }
    }, {
        get(target, key) {
            return key in target ? target[key].value : null;
        },
        set(target, key, value) {
            if (value && value.callback) {
               target[key] ? target[key].callback = value.callback : target[key] = {value: null, callback: value.callback};
               return true;
            } else {
              target[key] ? target[key].value = value : target[key] = {value, callback: () => {}};
              target[key].callback();
              return true;
            }
        }
    });
    
    proxy.first = {callback: () => console.log('got a callback')};
    
    proxy.first = false;