是否指定您可以在使用 for..of
进行迭代时删除 Set
实例中的任何元素,并且
- 您不会对一个元素进行多次迭代
- 除了您删除的元素之外,您不会错过迭代开始时集合中的任何其他元素
?
最佳答案
是的,在迭代集合时向集合添加元素和删除元素是完全可以的。 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
用空值替换它而不是删除它可以确保它不会弄乱迭代器的位置。
<小时/>正式
添加
以下是来自 %SetIteratorPrototype%.next
的规范的相关部分:
Repeat while index is less than the total number of elements of entries. The number of elements must be redetermined each time this method is evaluated.
集合迭代器继续逐一迭代条目。
来自Set.prototype.add
:
Append value as the last element of entries.
这确保了当向列表添加元素时,它将在迭代完成之前进行迭代,因为它总是在条目列表中获得一个新的槽。因此,这将按照规范的要求工作。
关于删除:
Replace the element of entries whose value is e with an element whose value is empty.
用空元素替换它而不是删除它可以确保现有迭代器的迭代顺序不会失去或排序,并且它们将继续正确地迭代集合。
使用代码
这是一个简短的代码片段,演示了这种能力
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;
}
关于javascript - 使用 for..of 迭代时删除 Set 中的元素是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28306756/