25

I found this gist to detect changes on specified fiels of a object : https://gist.github.com/3138469

But it bind an event only on one field.

Someone know a function or a tricks to detect change on an entire Javascript Object ?

2
  • 2
    I like to use Watch.js. Is that gist in your question taken from Watch.js? Commented Jul 20, 2012 at 11:32
  • Aouch, thanks a lot for this amazing gist ! Please post the answer and I will accept it. Thanks ! Commented Jul 20, 2012 at 11:43

5 Answers 5

28

2019 Update: These days this can be achieved using Proxy API in a much more efficient manner. The on-change library uses the Proxy API behind the scene to make this even easier.

2012 Update: I've just noticed that the author of Watch.js is referencing a library with much broader browsers' support. MultiGetSet.JS

When I want to achieve this I usually use Watch.js, you can watch a whole object or one attribute.

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

1 Comment

Thanks for updating this answer twice although last time about 8 years had passed. People like you make SO valuable. ✌️
3

This is currently not possible, you can only define getters/setters for individual properties.

Yet, there is a draft for Proxy objects which could do that. Today, it is only supported in Firefox' Javascript 1.8.5.

Comments

2

This is not possible using watch.js. it just detect the changes of an object or the attributes of the object. It DOESNT detect if we add an attribute to the object or change a new added attribute...

Comments

1

You can use the Proxy object to monitor (and intercept) changes made to an object. It is purpose built for what the OP is trying to do. Here's a basic example:

var targetObj = {};
var targetProxy = new Proxy(targetObj, {
  set: function (target, key, value) {
      console.log(`${key} set to ${value}`);
      target[key] = value;
      return true;
  }
});

targetProxy.hello_world = "test"; // console: 'hello_world set to test'

However, if you need to observe changes made to a nested object, then you need to use a specialized library such as Observable Slim (which I have authored).

It works like this:

var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
    console.log(JSON.stringify(changes));
});

p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]

Comments

0

Example using JavaScript's Proxy API.
You can reflect to changes made to some i.e: data object:

const react = (obj, cb) => new Proxy(obj, {
  set(t, key, val, r) {
    const old = t[key];
    const ref = Reflect.set(t, key, val, r);
    cb(key, val, old);
    return ref;
  }
});

// Data from server:
const data = { name: "John", age: 29 };

// Make user a Proxy of data, and react to changes with a callback:
const user = react(data, (key, val, old) => {
  console.log(`User changed ${key} value from: ${old} to: ${val}`);
});

// Change values on the Proxy!
user.name = "Johnatan";
user.age += 1;

// Let's test the original data
console.log("Original data is also updated:", { data });

Tip:
if you want to react immediately i.e: you want to update the DOM on page load (and also dynamically on a value change) wrap the Proxy inside Object.assign() (in order to trigger the setter):

const react = (obj, cb) => Object.assign(new Proxy(obj, {
  set(target, key, val) {
    const old = target[key];
    const ref = Reflect.set(...arguments);
    cb(key, val, old);
    return ref;
  }
}), obj);


const el = (sel, par = document) => par.querySelector(sel);

const data = { name: "John", age: 29 };

const user = react(data, (key, val) => {
  el(`[data-react="${key}"]`).textContent = val;
});

// Change values on the Proxy (Not on Data) in order to react:
setTimeout(() => user.name = "Johnatan", 1000);
setTimeout(() => user.age += 1, 2000);
Name: <span data-react="name"></span>
Age: <span data-react="age"></span>

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.