2

I am using Object.defineProperty to override getter and setter on an object, so that I can listen to all the mutation events.

var a = {};
Object.defineProperty(a, key, {
  get: function(){
    ..
  },
  set: function(val){
    ..
  }
}

This works fine, but there's one caveat--I need to know in advance what attributes I want to listen to--which means I need to iterate through all the keys I want to watch in the beginning.

If I wanted to randomly assign a new attribute during runtime like this:

a.new_attr=1;

it wouldn't work because I haven't defined the new_attr property yet.

Is there a way to either:

  1. dynamically run Object.defineProperty() when I assign the attribute for the first time; or
  2. any other way to handle situations like this? (Maybe some way to monitor ALL attributes without specifying the keys)

1 Answer 1

3

I think what you really want to use is a Proxy. Proxies allow you to intercept events such as get and set.

var obj = {
  a: 1,
  b: 2
};
var proxiedObj = new Proxy(obj, {
  get: function(target, name) {
    console.log(`get: ${name}`);
    return target[name];
  },
  set: function(target, prop, value) {
    console.log(`set: ${prop}`);
    target[prop] = value;
  }
});

console.log(proxiedObj.a);
console.log(proxiedObj.b);

// Notice that it still works even on new properties
proxiedObj.c = 3;
console.log(proxiedObj.c);

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

5 Comments

Note: This only works in ES2015/ES6+ environments and cannot be transpiled.
@nils Very good point. Technically, it can be transpiled (sort of) but is incredibly slow.
Oh wow, I hadn't seen that solution before. Very creative, but not suitable for production.
Thanks for the answer, unfortunately i'm looking for a classic JS solution. So would this mean there's no solution that works for ordinary JS that will work out of the box in all browsers? I am trying hard not to use the new versions of ES because I want to keep it simple.
@Vlad There's no solution that will work with ES5. Proxies were made specifically to handle situations like these. There's no comparable mechanism in ES5. As you stated, you can make it work if all of the keys are known before hand but you have no way of hooking in to new keys.

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.