How to use global variables in JavaScript

Global variables are variables that are accessible from anywhere in the JavaScript code, regardless of the scope. They can be useful for storing values that are shared across different functions or modules, such as constants, configuration options, or global state. However, using global variables can also have some drawbacks, such as:

  • They can cause conflicts or overwrite other variables with the same name, especially if they are defined by different scripts or libraries.
  • They can make the code harder to read, test, and debug, as it is not clear where the variables are coming from or how they are modified.
  • They can introduce unwanted side effects or dependencies, as changing a global variable can affect other parts of the code that rely on it.

In JavaScript, you can use global variables across multiple files by attaching them to the global object (usually window in a web browser environment) or by using a module system to import and export variables between files.

Using the global object

The global object in JavaScript is an object that contains variables and functions that are available anywhere in the code. Depending on the environment where the JavaScript code is running, the global object may have a different name and properties. Here are some examples of the global object in different environments:

In a browser environment, the global object is usually accessible via the window property, which is a reference to the Window object. The window property contains several additional properties and methods that allow us to control the web browser window as well as the document itself. The window property also has synonyms such as self and frames, which can be used to access the global object as well.

window.myName = "byby"; // creates a global variable myName
console.log(myName); // prints "byby"
console.log(window.myName); // prints "byby"

In Node.js, the global object is accessible via the global property, which is a reference to the globalThis object. The global property contains several properties and methods that are specific to the Node.js environment, such as global.process and global.console.

In Web Workers, the global object is accessible via the self property, which is a reference to the WorkerGlobalScope object. The self property contains several properties and methods that are specific to the Web Workers environment, such as self.postMessage and self.importScripts.

To avoid confusion and inconsistency, there is a proposal to introduce a standard property called globalThis that will be available in all environments and will always refer to the global object. This way, we can write portable JavaScript code that works in multiple environments without having to worry about the different names and properties of the global object.

// script1.js
globalThis.myName = "byby";

// script2.js
console.log(globalThis.myName); // prints "byby"

Using a module system

Modern JavaScript encourages using a module system to import and export variables between files. This approach allows for better encapsulation and avoids polluting the global namespace.

Module systems do not have direct access to the global scope, which means you cannot define or use global variables in them. You can create a module that exports the variables you want to use globally, and then import them in any other module that needs them.

Here’s an example using ES modules, which are supported in most modern browsers and are widely used in both client-side and server-side JavaScript environments.

// globals.js
export const PI = 3.14; // export a global constant
export let counter = 0; // export a global variable

// module1.js
import { PI, counter } from "./globals.js"; // import the global variables
console.log(PI); // use the global constant
// will log 3.14
counter++; // modify the global variable

// module2.js
import { counter } from "./globals.js"; // import the global variable
console.log(counter); // use the global variable
// will log 1

Or using CommonJS, which was originally designed for server-side JavaScript environments, specifically in the context of the Node.js runtime.

// globals.js
module.exports = {
  PI: 3.14, // export a global constant
  counter: 0 // export a global variable
};

// module1.js
var globals = require("./globals.js"); // import the global variables
console.log(globals.PI); // use the global constant
// will log 3.14
globals.counter++; // modify the global variable

// module2.js
var globals = require("./globals.js"); // import the global variables
console.log(globals.counter); // use the global variable
// will log 1

Using a bundler

Most modern build tools, like Webpack and Rollup, can handle both CommonJS and ES modules, allowing developers to use either based on their needs.

When using a bundling tool like Webpack to define global variables at build time, you can use the DefinePlugin to configure some constants that are available at compile time, and then use them in your modules. For example:

// webpack.config.js
const webpack = require("webpack");

module.exports = {
  // ...
  plugins: [
    new webpack.DefinePlugin({
      FOO: JSON.stringify("bar"), // define a global constant
    }),
  ],
};

// module1.js
console.log(FOO); // use the global constant
// will log "bar"

Best practices

It is generally recommended to avoid or minimize the use of global variables in JavaScript, and follow some best practices, such as:

  • Declare global variables explicitly with the var, let, or const keywords at the top level of the script, or use the window object to access the global scope.
  • Use a unique and descriptive name for global variables, and avoid using common or generic names that may clash with other variables.
  • Use a namespace or a module pattern to group related global variables and functions into a single object, and avoid polluting the global scope with too many variables.
  • Use local variables whenever possible, and pass them as arguments or return values to communicate between functions.
  • Use closures or this to create private variables that are accessible only within a specific function or object.