为何同一Set对象生成的同类型迭代器不严格相等?
为何同一Set对象生成的两个迭代器不严格相等?
先看你给出的代码示例:
let set = new Set([1,2,'3']); console.log(set.keys === set.values); // true console.log(set.keys === set[Symbol.iterator]); // true console.log(set.values === set[Symbol.iterator]); // true console.log(set.keys() === set.values()); // false // console.log输出形式一致 console.log(set.keys()); // [Set Iterator] { 1, 2, '3' } console.log(set.values()); // [Set Iterator] { 1, 2, '3' } // Set迭代器自身也不相等 let keys1 = set[Symbol.iterator](); let keys2 = set[Symbol.iterator](); console.log(keys1 === keys2); // false
核心原因很直接:每次调用迭代器生成函数(不管是keys()/values()/Symbol.iterator()),都会创建并返回一个全新的迭代器对象。
根据ECMAScript 2021规范:
Set.prototype.keys属性的初始值与values属性的初始值为同一函数对象。
而Set.prototype.values()的执行步骤明确是:
- 令S为this值。
- 返回?CreateSetIterator(S, value)。
这里的CreateSetIterator是规范定义的抽象操作,它的作用就是为目标Set创建一个新的迭代器实例——每个迭代器都独立维护自己的遍历状态(比如当前遍历到哪个元素)。如果两次调用返回同一个迭代器对象,那两个迭代器会共享状态,比如你用第一个迭代器遍历到一半,第二个迭代器的位置也会跟着变,这显然不符合遍历的预期。
严格相等运算符===比较对象时,判断的是两个变量是否指向内存中的同一个引用。因为每次调用生成的迭代器都是新对象,引用不同,所以结果自然是false。哪怕控制台输出的迭代器形式看起来一样,它们本质上是两个独立的对象。
内容的提问来源于stack exchange,提问作者Ross Jacobs
相关产品推荐
相关产品推荐

