Trace the fixed program
Build topic=html and topic=css plus the note A&B C. Serialize, parse again, and compare the recovered values. No address needs to be opened.
const params=new URLSearchParams();params.append('topic','html');params.append('topic','css');params.set('note','A&B C');
const encoded=params.toString();const parsed=new URLSearchParams(encoded);
console.log(JSON.stringify({encoded,topics:parsed.getAll('topic'),note:parsed.get('note')}));
{"encoded":"topic=html&topic=css¬e=A%26B+C","topics":["html","css"],"note":"A&B C"}| Data | Serialized form | Recovered value |
|---|---|---|
| topic: html, css | topic=html&topic=css | ["html","css"] |
| note: A&B C | note=A%26B+C | A&B C |
Explain the result
URLSearchParams keeps ordered name/value pairs. append adds another pair; getAll retrieves every value for that name. Its form-url-encoded serialization escapes & as %26 and spaces as +. set replaces the matching name’s values; it is not interchangeable with append for repeated filters.
Test the alternative
Raw concatenation treats & as a separator and breaks the note. Converting repeated entries to an object retains only the later topic value.
const broken=new URLSearchParams('note=A&B C');const repeated=new URLSearchParams('topic=html&topic=css');
console.log(JSON.stringify({note:broken.get('note'),extraKeys:[...broken.keys()],object:Object.fromEntries(repeated)}));
{"note":"A","extraKeys":["note","B C"],"object":{"topic":"css"}}Work the boundary case
Does an empty note disappear, and how is a literal plus sign preserved?
Show the worked answer
An empty note remains present as note=. A plus passed through append is encoded as %2B and decoded back to +; a raw + in a parsed query denotes a space.
const params=new URLSearchParams();params.append('note','');params.append('symbol','+');const parsed=new URLSearchParams(params.toString());
console.log(JSON.stringify({encoded:params.toString(),hasNote:parsed.has('note'),note:parsed.get('note'),symbol:parsed.get('symbol'),rawPlus:new URLSearchParams('symbol=+').get('symbol')}));
{"encoded":"note=&symbol=%2B","hasNote":true,"note":"","symbol":"+","rawPlus":" "}