Search code examples
node.jsurlsearchparams

why does the URLSearchParams iterator skip every other k,v pair


Consider the following simple function with a URLSearchParams iterator.

const foo = (qs) => {
    const sp = new URLSearchParams(qs);

    console.log(`pre: ${sp}`);

    for (const [key, val] of sp.entries()) {
        console.log(`'${key}: ${val}'`);
        sp.delete(key);
    }

    console.log(`post: ${sp}`);
}

foo('a=1&b=2&c=3&d=4');

With the sp.delete(key) line commented out, it prints

pre: a=1&b=2&c=3&d=4
'a: 1'
'b: 2'
'c: 3'
'd: 4'
post: a=1&b=2&c=3&d=4

But when I uncomment that line, the output is

pre: a=1&b=2&c=3&d=4
'a: 1'
'c: 3'
post: b=2&d=4

I expect all the keys to be deleted, but in the second case, the iterator skips over every other key,val pair. Why? Where am I being "stupid" or "blind" to my error?

Note: I realize I am changing the iterator while iterating over it, but am not able to wrap my head around skipping every other key


Solution

  • This is because you are modifying the underlying data structure (the URLSearchParams object) that the iterator (for...of loop) is using. and, when you call sp.delete(key) inside the loop this causes the iterator to skip over the next key-value pair, because the iterator's internal state is updated when the data structure changes.

    To fix this, iterate over the copy of entries i.e:

    for (const [key, val] of Array.from(sp.entries())) {
        console.log(`'${key}: ${val}'`);
        sp.delete(key);
    }