Все ли модифицирующие методы вызывают установленную ловушку Прокси-массива - PullRequest
1 голос
/ 25 сентября 2019

Чтобы синхронизировать два или несколько массивов, я пытаюсь использовать этот простой прокси

let a1 = [];
let a2 = [];
let targets = [a1, a2];

let proxy = new Proxy(targets[0], {
    set: (target, property, value) => {
      targets.forEach(t => t[property] = value);
      return true;
    }
});

Цель состоит в том, чтобы повторить все изменения от a1 до a2.Тесты на Chrome, Firefox и Node показывают , что все методы Array внутренне вызывают установщик свойств , так что эта простая реализация прекрасно работает.Но я не могу найти какое-либо утверждение, если это гарантировано каким-либо образом.

Реальная реализация прокси будет выглядеть немного сложнее, если иметь дело с вложенными массивами и объектами, но общий вопрос остается прежним: Можно ли полагаться на тот факт, что методы массива, которые изменяют содержимое массива, всегда проходят через установленную ловушку?

См. Этот пример:

let a1 = [];
let a2 = [];  

let targets = [a1, a2];
let proxy = new Proxy(targets[0], {
    set: (target, property, value) => {
      targets.forEach(t => t[property] = value);
      return true;
    }
});

proxy[0] = 0;
log('proxy[0] = 0');
proxy[0] = 1;
log('proxy[0] = 1');
proxy.push(1);
log('proxy.push(1)');
proxy.length = 1;
log('proxy.length = 1');
proxy.splice(0, 1, 1, 2, 3);
log('proxy.splice(0, 1, 1, 2, 3)');
proxy.fill(3, 1, 2);
log('proxy.fill(3, 1, 2)');
proxy.shift();
log('proxy.shift()');
proxy.unshift(2);
log('proxy.unshift(2)');

function log(msg) {
  let pre = document.querySelector('pre');
  if (!pre) {
    pre = document.createElement('pre');
    document.body.appendChild(pre);
  }
  pre.innerHTML = msg + '\n' + JSON.stringify(a1) + '\n' + JSON.stringify(a2) + '\n\n' + pre.innerHTML;
}

1 Ответ

1 голос
/ 25 сентября 2019

Да, это безопасно.Все операции, которые изменяют массив, такие как присвоение индекса или вызов push или splice, вызывают операцию Set.

Например, для push см. здесь ;

б.Выполнить?Set (O,! ToString (len), E, ​​true).

где Set в основном выполняет:

>O.[[Set]](P, V, O).

, который вызывает внутренний метод [[Set]] рассматриваемого объекта.Если рассматриваемый объект является прокси, то он проходит процесс, описанный здесь :

Пусть будет ловушка?GetMethod (обработчик, "set").

Если ловушка не определена, то

a.Вернуть ?target. [[Set]] (P, V, Receiver).

Пусть booleanTrapResult будет!ToBoolean (? Call (trap, handler, «target, P, V, Receiver»)).

, который явно вызывает ловушку set на Прокси, если она существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...