Поведение targetArray.reduce при изменении targetArray.length в функции редуктора - PullRequest
1 голос
/ 09 июля 2019

Этот вопрос предназначен прежде всего для тех, кто работает со спецификацией ECMAScript и / или реализует ее.

spec определяет алгоритм для Array.prototype.reduce(callbackfn[,initialValue]). Посмотрите, что алгоритм, шаг 2, читает Let len be ? ToLength(? Get(O, "length")), и после этого я понимаю, что len никогда больше не обновляется. Однако взгляните на это:

const a = [0,1,2,3,4];
a.reduce(p=>{
  a.splice(0,1);
  console.log(a);
  return p;
},a);
// Logs:
// [1,2,3,4]
// [2,3,4]
// [3,4]
// and that's it

Поскольку предполагается, что итерации выполняются while k<len (k - счетчик итераций), такое поведение предполагает, что в попытках, которые я пробовал (Chrome, Edge, Node), len обновляется на каждой итерации до длины a текущей итерации.

Это действительно предполагаемое поведение? Есть ли конкретная причина, по которой len целенаправленно обновляется на каждой итерации вместо того, чтобы сохранять ее фиксированной с самого начала, как указано в спецификации?

1 Ответ

3 голосов
/ 09 июля 2019

Поведение, которое вы видите, связано с шагом 9.2: обратный вызов вызывается только тогда, когда свойство присутствует в объекте.Он выполняет итерацию 5 раз, но после удаления 3 элементов в четвертой и пятой итерации a.hasOwnProperty(3) и a.hasOwnProperty(4) имеют значение false.

Мы можем лучше всего продемонстрировать это с помощью прокси:

const a = [0,1,2,3,4];
new Proxy(a, {
	has(target, p) { const v = Reflect.has(target, p); console.log("has", p, v); return v },
	get(target, p) { const v = Reflect.get(target, p); console.log("get", p, v); return v }
}).reduce((p, e) => {
  a.length--;
  console.log("at " + e, a);
  return p;
}, null);

Или, альтернативно, путем вызова reduce для объекта, чьи .length изменения не влияют на свойства:

const a ={0:0,1:1,2:2,3:3,4:4,length:5,reduce:Array.prototype.reduce};
a.reduce((p, e) => {
  a.length--;
  console.log("at " + e, a);
  return p;
}, null);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...