Even in a single-threaded environment, passing a struct around containing values allows you to implement dynamic scoping, which in this case means, you can easily call some functions with some overridden values in the global struct, and that code can also pass around modified versions of the struct, and so on, and it is all cleanly handled and scoped properly. This has many and sundry uses. If you just have a plain global variable this is much more difficult.
Although Perl 5 has a nice feature where all global variables can automatically be treated this way by using a "local" keyword. It makes the global variables almost useful, and in my experience, makes people accidentally splattering globals around do a lot less damage than they otherwise would because they don't have to make explicit provision for scoped values. I don't miss many features from Perl but this is on the short list.
And do you always know beyond any reasonable doubt that your code will be single-threaded for all time? Because the moment this changes, you're in for a world of pain.
Wrapping the globals into to a struct context #ifdef MULTI-THREADED and adding this ctx for each call as first call is a matter of minutes. I've done this multiple times.
Much worse is protecting concurrent writes, eg to an object or hash table
If the discussion here is meant to be solely about JavaScript, then I'll happily consider all my comments in this thread to be obsolete, since I don't have particularly strong opinions about that language since I don't use it a lot.
I was under the impression that many people here were discussing the usage of global variables more generally, though.