JavaScript中Set的forEach死循环问题:为何操作顺序影响结果?
为什么两段Set的forEach代码执行结果不同?
先看两段代码:
第一段(触发死循环)
const s = new Set([1]); s.forEach(e => { s.delete(e) s.add(e) })
第二段(正常结束)
const s = new Set([1]); s.forEach(e => { s.add(e) s.delete(e) })
核心原因:Set迭代器的遍历规则
Set的forEach依赖内置迭代器工作,迭代器不会单纯按初始元素数量遍历,而是跟踪元素的插入顺序和遍历状态,遍历过程中修改集合的操作会直接影响迭代器的行为:
第一段死循环的具体逻辑
- 初始Set包含元素
1,forEach启动迭代,迭代器指向1并执行回调。 - 先执行
s.delete(e):Set变为空,迭代器原本指向的元素消失,遍历位置被重置。 - 再执行
s.add(e):新的1被插入Set,迭代器会把这个新插入的元素标记为未遍历的元素。 - 回调执行完后,
forEach会请求迭代器的下一个元素,发现还有刚添加的1,于是再次触发回调,重复上述步骤,陷入无限循环。
第二段正常结束的具体逻辑
- 初始Set包含元素
1,forEach启动迭代,迭代器指向1并执行回调。 - 先执行
s.add(e):因为Set不允许重复元素,这个操作不会改变集合(1已经存在),迭代器的遍历位置不受影响。 - 再执行
s.delete(e):Set变为空,但迭代器已经完成了对原元素1的遍历记录。 - 回调执行完后,
forEach请求迭代器的下一个元素,发现没有未遍历的元素,遍历直接结束。
内容的提问来源于stack exchange,提问作者Turbo Zhang
相关产品推荐
相关产品推荐

