Is it specified that you can delete any element in an instance of Set
while iterating using for..of
and that
My answer is yes, if you're okay with it continuing onto the next value in the Set in the next iteration after the deletion. It doesn't even seem to matter which instance of the Set you're currently on in the iteration process. Pretty ideal!
Here's my test code:
s = new Set([ { a: 0 }, { a: 1 }, { a: 2 }, { a: 3 } ]);
do {
for (let x of s) {
console.log(x.a);
if (Math.random() < 0.2) {
console.log('deleted ' + x.a);
s.delete(x);
}
}
} while (s.size > 0);
In Firefox 75.0, it works just fine. Sets are supposed to maintain their insertion order, and it does, it prints it out in that order as it iterates through. Regardless of what gets deleted, it continues in the insertion order:
0
1
2
3
0
1
deleted 1
2
3
0
2
deleted 2
3
0
3
0
deleted 0
3
3
...
3
3
deleted 3
I also tested with similar code but that doesn't use the current instance of the iteration process:
sCopy = [{ a: 0 }, { a: 1 }, { a: 2 }, { a: 3 }];
s = new Set(sCopy);
do {
for (let x of s) {
console.log(x.a);
if (Math.random() < 0.2) {
let deleteMe = Math.floor(Math.random() * s.size);
console.log('deleted ' + sCopy[deleteMe].a);
s.delete(sCopy[deleteMe]);
sCopy.splice(deleteMe, 1);
}
}
} while (s.size > 0);
I had to use an adjacent array because there's no way to look up a random index of a Set, to delete a random instance. So I just created the Set from the array so it uses the same object instances.
That works great as well, as you can see:
0
deleted 1
2
deleted 2
3
0
3
0
deleted 0
3
3
3
3
deleted 3
And yes... I even tested with random object instance insertion as well... Same deal, I won't post the output this time:
sCopy = [{ a: 0 }, { a: 1 }, { a: 2 } ];
s = new Set(sCopy);
do {
for (let x of s) {
console.log(x.a);
if (Math.random() < 0.1) {
let newInstance = { a: Math.random() * 100 + 100 };
console.log('added ' + newInstance.a);
s.add(newInstance);
sCopy.push(newInstance);
}
if (Math.random() < 0.2) {
let deleteMe = Math.floor(Math.random() * s.size);
console.log('deleted ' + sCopy[deleteMe].a);
s.delete(sCopy[deleteMe]);
sCopy.splice(deleteMe, 1);
}
}
} while (s.size > 0);