At w3schools there is written:
If you declare a variable, without using “var”, the variable always becomes GLOBAL.
Is it useful to declare global variable inside the function? I can imagine to declare some global variables in some event handler, but what is it good for? Better usage of RAM?
No, there’s no RAM benefit or anything like that.
What w3schools is talking about is something I call The Horror of Implicit Globals. Consider this function:
Seems simple enough, but it returns
NaN, not11, because of the typo on thevaraible2 = 6;line. And it creates a global variable with the typo’d name:This is because the function assigns to
varaible2(note the typo), butvaraible2isn’t declared anywhere. Through the mechanics of the scope chain in JavaScript, this ends up being an implicit assignment to a (new) property on the global object (which you can access aswindowon browsers, orglobalThisin all modern environments [including modern browsers]).That’s just a "feature" of loose-mode JavaScript, assigning to a completely undeclared identifier isn’t an error; instead, it creates a property on the global object, and properties on the global object are global variables. (Up through ES5, all globals were properties of the global object. As of ES2015, though, a new kind of global was added that isn’t a property of the global object. Global-scope
let,const, andclasscreate the new kind of global.)My example is a typo, but of course, you could do it on purpose if you wanted. But I’d strongly advise not doing so. Instead, I recommend always using strict mode, either directly or by using ECMAScript modules (ESM, JavaScript’s own module system added in ES2015), which are strict by default. Strict mode makes assigning to an undeclared identifier an error rather than silently creating a global. If we’d been using strict mode, the problem with the
foofunction above would have been much more obvious and easier to diagnose:Somewhat tangential, but in general I’d recommend avoiding globals wherever possible. The global namespace is already very, very cluttered on browsers, which makes it easy to accidentally create conflicts. The browser creates a global for every element in the DOM with an
id, for most elements with aname, and has several predefined globals of its own (likenameandtitle) which can easily conflict with your code.Instead, use JavaScript modules (ESM). Top-level declarations in a module aren’t globals, they’re only global to the code in that module. Then you can use
exportto intentionally expose the parts of your code you want other modules to be able to use (viaimport).Here in 2022, you can almost always use ESM; it’s well-supported by modern browsers and by Node.js. If you have to target an obsolete environment that doesn’t support it (like Internet Explorer), you can use a bundler to wrap up your ESM code into a bundle instead.
If for some reason you can’t use ESM, you can do what we used to do before modules were standardized: Use a scoping function wrapped around your code:
And if you do that, you might want to enable strict mode:
…which, as mentioned, has the advantage of turning assignments to undeclared identifiers into errors (along with various other helpful things).
If you have to make something global, you can assign to a property on
window. (In modern environments, I’d say you can assign to a property onglobalThis, but if you can’t use ESM, it’s unlikely the environment you’re targeting supportsglobalThis.)