Detecting changes in a Javascript array using the Proxy object
From what I can read from the MDN page, you can create a general handler where you can handle all the changes to any object.
In a sense, you write an interceptor, that will intervene each time you get a value from the array or set a value. You can then write your own logic to follow the changes.
var arrayChangeHandler = {
get: function(target, property) {
console.log('getting ' + property + ' for ' + target);
// property is index in this case
return target[property];
},
set: function(target, property, value, receiver) {
console.log('setting ' + property + ' for ' + target + ' with value ' + value);
target[property] = value;
// you have to return true to accept the changes
return true;
}
};
var originalArray = [];
var proxyToArray = new Proxy( originalArray, arrayChangeHandler );
proxyToArray.push('Test');
console.log(proxyToArray[0]);
// pushing to the original array won't go through the proxy methods
originalArray.push('test2');
// the will however contain the same data,
// as the items get added to the referenced array
console.log('Both proxy and original array have the same content? '
+ (proxyToArray.join(',') === originalArray.join(',')));
// expect false here, as strict equality is incorrect
console.log('They strict equal to eachother? ' + (proxyToArray === originalArray));
Which then outputs:
getting push for
getting length for
setting 0 for with value Test
setting length for Test with value 1
getting 0 for Test
Test
The caveat for the proxy, is that everything which is defined on an object, will be intercepted, which can be observed when using the push
method.
The original object that will be proxied doesn't mutate, and changes done to the original object will not be caught by the proxy.
You can do somthing like this
new Proxy([], {
get(target, prop) {
const val = target[prop];
if (typeof val === 'function') {
if (['push', 'unshift'].includes(prop)) {
return function (el) {
console.log('this is a array modification');
return Array.prototype[prop].apply(target, arguments);
}
}
if (['pop'].includes(prop)) {
return function () {
const el = Array.prototype[prop].apply(target, arguments);
console.log('this is a array modification');
return el;
}
}
return val.bind(target);
}
return val;
}
});