Обнаружение изменений в массиве Javascript с использованием объекта Proxy
Относительно тривиально наблюдать за изменениями в массиве в Javascript.
Один метод, который я использую, выглядит следующим образом:
// subscribe to add, update, delete, and splice changes
Array.observe(viewHelpFiles, function(changes) {
// handle changes... in this case, we'll just log them
changes.forEach(function(change) {
console.log(Object.keys(change).reduce(function(p, c) {
if (c !== "object" && c in change) {
p.push(c + ": " + JSON.stringify(change[c]));
}
return p;
}, []).join(", "));
});
});
Тем не менее, я недавно прочитал, что Array.observe
устарела, и мы должны вместо этого использовать объект прокси.
Как мы можем обнаружить изменения в массиве объекта Proxy? Я не могу найти каких-либо примеров, кто-то заинтересован в разработке?
2 ответа
Из того, что я могу прочитать со страницы MDN, вы можете создать общий обработчик, в котором вы сможете обрабатывать все изменения любого объекта.
В некотором смысле вы пишете перехватчик, который будет вмешиваться каждый раз, когда вы получаете значение из массива или устанавливаете значение. Затем вы можете написать свою собственную логику, чтобы следить за изменениями.
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));
Который затем выводит:
getting push for
getting length for
setting 0 for with value Test
setting length for Test with value 1
getting 0 for Test
Test
Предостережение для прокси-сервера заключается в том, что все, что определено для объекта, будет перехвачено, что можно наблюдать при использовании push
метод.
Исходный объект, который будет прокси, не видоизменяется, и изменения, внесенные в исходный объект, не будут отслеживаться прокси.
Вы можете сделать что-то вроде этого
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;
}
});