在使用for..of进行迭代时删除Set中的元素是否安全?

时间:2015-02-03 19:05:02

标签: javascript iterator set ecmascript-6

是否指定在使用Set进行迭代时可以删除for..of实例中的任何元素

  • 您不会在元素上多次迭代
  • 你不会错过迭代开始时集合中除你删除的元素之外的任何其他元素

1 个答案:

答案 0 :(得分:25)

,在迭代时添加元素并删除元素是完全没问题的。这个用例被考虑并在JavaScript 2015(ES6)中得到支持。它将使其保持一致状态。请注意,这也适用于使用forEach进行迭代。

直观地:

设置迭代算法基本上看起来像这样:

Set position to 0
While position < calculateLength() // note it's 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

用空值替换它而不是删除它确保它不会弄乱迭代器&#39;位置。


形式上

加成

以下是%SetIteratorPrototype%.next的规范的相关部分:

  

重复索引小于条目元素的总数。 每次评估此方法时,必须重新确定元素数量。

set迭代器继续逐个迭代这些条目。

来自Set.prototype.add

  

将值附加为条目的最后元素。

这确保了在向列表添加元素时,它将在迭代完成之前进行迭代,因为它总是在条目列表中获得新的插槽。因此,这将符合规范要求。

至于删除:

  

将值为e 的条目元素替换为值为空的元素。

用空元素替换它而不是删除它确保现有迭代器的迭代顺序不会输出或顺序,并且它们将继续正确迭代集合。

使用代码

以下是演示此功能的简短代码段

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

其中记录了数字1到10.这是一个不用于...的版本,您今天可以在浏览器中运行:

&#13;
&#13;
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;
}
&#13;
&#13;
&#13;