Building query params which append to URL in a browser
Your main question

I have trouble understanding it, because:


minor reason:
(unless I'm missing something obvious) whatever way you encode the array parts, the resulting query string is quite valid in both cases;
so the only possible criterion for choosing a method rather than the other one would be to find which one is faster... and this sounds a bit overkill!
major reason:
you initially referred to the PHP http_build_query() function, so I'd expect you work the same, i.e. for a given key: [val_1, val_2]:


you're currently returning key=val_1,val_2
while it should be key=val_1&amp;key=val_2



To match the latter case, I'd suggest something like this:

const output = Object.entries(params).map(
  (pair) =&gt; {
    let [key, val] = pair;
    // normalize val to always an array
    val = (val instanceof Array) ? val : [val];
    // encode key only once
    key = encodeURIComponent(key);
    // then make a different query string for each val member
    return val.map(
      (member) =&gt; `${key}=${encodeURIComponent(member)}`
    ).join('&amp;');
  }
).join('&amp;');


Your complementary question

To implement null or undefined, first you have to decide how they must be managed: they might be simply omitted, or included with no value (its often useful to have query params where only its presence/absence is meaningful for the underlying application).

Anyway you may simply add any of these capabilities; instead of

    return val.map(
      (member) =&gt; `${key}=${encodeURIComponent(member)}`
    ).join('&amp;');


you can include null/undefined params simply with:

return val.map(
  (member) =&gt; (member ? `${key}=${encodeURIComponent(member)}` : `${key}`)
).join('&amp;');


(NOTE: it's up to you to enhance this with more precise tests if desired, in order to keep 0 as key=0, or '' as key=)

or you can omit them with a slightly different method:

return val.reduce(
  (result, member) =&gt; {
    if (member) {
      result.push(`${key}=${encodeURIComponent(member)}`);
    }
    return result;
  },
  []
).join('&amp;');