Подтвердить что ты не робот

Безопасно ли удалять элементы в наборе во время итерации с помощью .of?

Указано, что вы можете удалить любой элемент в экземпляре Set при повторении с помощью for..of и

  • вы не будете повторять несколько раз на элементе
  • вы не пропустите ни одного другого элемента, который был в наборе в начале итерации, кроме тех, которые вы удаляете.

?

4b9b3361

Ответ 1

Да, прекрасно добавлять элементы и удалять элементы в набор при его повторении. Этот вариант использования рассмотрен и поддерживается в JavaScript 2015 (ES6). Он оставит его в постоянном состоянии. Обратите внимание, что это также относится к itearting с forEach.

Наглядно:

Итерационный алгоритм установки в основном выглядит примерно так:

Set position to 0
While position < calculateLength() // note it calculated on each iteration
    return the element at set.entryList[position]

Добавление выглядит просто так:

If element not in set
   Add element to the _end_ of the set

Таким образом, это не мешает существующим итерациям - они будут итерации.

Удаление выглядит примерно так:

Replace all elements with are equal to `element` with a special empty value

Замена его пустым значением, а не его удаление гарантирует, что он не испортит позиции итераторов.


Формально

Добавление

Вот соответствующая часть спецификации от %SetIteratorPrototype%.next:

Повторить, пока индекс меньше, чем общее количество элементов записей. Количество элементов должно быть переопределено каждый раз, когда этот метод оценивается.

Итератор set выполняет итерацию записей один за другим.

От Set.prototype.add:

Добавить значение как элемент last.

Это гарантирует, что при добавлении элементов в список он будет итерирован до завершения итерации, так как он всегда получает новый слот в списке записей. Таким образом, это будет работать как мандат спецификации.

Что касается удаления:

Замените элемент записей, значение которого e , с элементом, значение которого пусто.

Замена его пустым элементом, а не его удаление, гарантирует, что порядок итераций существующих итераторов не исчезнет или не будет упорядочен, и они будут продолжать корректно повторять набор.

С кодом

Ниже приведен фрагмент кода, демонстрирующий эту способность.

var set = new Set([1]);
for(let item of set){
   if(item < 10) set.add(item+1);
   console.log(item);
}

Коды регистрируют числа от 1 до 10. Вот версия, которая не используется для... вы можете запустить в своем браузере сегодня:

var set = new Set([1]);
for (var _i = set[Symbol.iterator](), next; !(next = _i.next()).done;) {
   var item = next.value;
   if (item < 10) set.add(item + 1);
   document.body.innerHTML += " " + item;
}