Yes,在迭代集合时添加元素和删除元素是完全可以的。 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
用空值替换它而不是删除它可以确保它不会弄乱迭代器的位置。
Formally
Addition
这是规范的相关部分%SetIteratorPrototype%.next
:
当索引小于条目的元素总数时重复。每次评估此方法时都必须重新确定元素的数量。
设置迭代器继续逐一迭代条目。
From 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。这是一个不使用 for... 的版本,您今天可以在浏览器中运行:
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;
}