3

For any variable or property thereof, is there a way to know when its value is set?

For example, say I have:

let x = { 'a': 1, 'b': 2 };
// x.a's set operation is linked to a method
x.a = 3; // the method is automatically called

Is there a way I can call a function when a's value is changed? Lots of code would be changing this value; I don't want to add the method call all over the place.

I'm aware of Proxies, but to use them seems to require a separate variable. Meaning, x can't be a proxy of itself.

Preferably this technique would work with primitive and non-primitives.

6
  • Is there a way I can call a function when a's value is changed? use setters and getters Commented Mar 28, 2019 at 1:23
  • 1
    Sure x can be a Proxy.... x = new Proxy(x, handler) Commented Mar 28, 2019 at 1:24
  • @charlietfl - Wouldn't that cause a loop? The handler would include a set method which would trigger itself. Commented Mar 28, 2019 at 1:32
  • the handler shouldn't use x. anything since setting a value will call set: function(obj, prop, value) { ... so obj[prop] = value won't loop :p but x[prop] = value would not be good Commented Mar 28, 2019 at 1:36
  • 1
    @Karric basic example works fine jsfiddle.net/3pfyxu9j Commented Mar 28, 2019 at 1:42

2 Answers 2

3

x can't be a proxy of itself

Sure it can. You can change the variable to point to a Proxy by simply doing

x = new Proxy(x, handler)

Primitive example:

const handler = {
  set: function(obj, prop, value) {
    console.log('setting prop: ', prop, ' to ', value)
    obj[prop] = value;
    return true;
  }
};

let x = { 'a': 1, 'b': 2 };

x = new Proxy(x, handler);

x.a = 3; // the method is automatically called

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

3 Comments

I've run into an issue. Given x = { 'a': [1] }, and I do x.a = [2], the set trap is not called. Why? Is there a trap for re-assignment?
Can't reproduce here jsfiddle.net/7uxjmszf. Same demo as in comments above, I just changed to array values
Weird, your example works, I'll have to see how my code differs.
3

To be honest, use Proxy if you can

If you really can't use Proxy, you could achieve this using using setters and getters

Though it does mean re-declaring your original x object, I assume it's declared inline like the Minimal, Complete and Verifiable Example in your question

let x = {
  _a: 1,
  _b: 2,
  get a() {
    return this._a;
  },
  get b() {
    return this._b;
  },
  set a(value) {
    console.log(`changing a from ${this._a} to ${value}`);
    this._a = value;
  },
  set b(value) {
    console.log(`changing b from ${this._b} to ${value}`);
    this._b = value;
  }
};
x.a = 3;

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.