What is the correct way to define global variable in ES6 modules?

26,722

Solution 1

There are several ways to have global values available in your application.

Using ES6 modules, you can create a constant which you export from your module. You can then import this from any other module or component, like so:

/* Constants.js */
export default {
    VALUE_1: 123,
    VALUE_2: "abc"
};

/* OtherModule.js */
import Constants from '../Constants';

console.log(Constants.VALUE_1);
console.log(Constants.VALUE_2);

Alternatively, some JS bundling tools provide a way to pass values into your components at build time.

For example, if you're using Webpack, you can use DefinePlugin to configure a few constants available at compile time, like so:

/* Webpack configuration */
const webpack = require('webpack');

/* Webpack plugins definition */
new webpack.DefinePlugin({
    'VALUE_1': 123,
    'VALUE_2': 'abc'
});

/* SomeComponent.js */
if (VALUE_1 === 123) {
    // do something
}

Solution 2

You can grab the global object with an indirect eval call.

// this weird syntax grabs the global object
const global = (0,eval)("this");
// (0,eval) === eval; but the first one is an indirect evaluation
// inside indirect evaluation of eval, "this" is global object
// this takes advantage of that fact to identify "global"

// then set whatever global values you need
global.VALUE_1 = 123;
global.VALUE_2 = "abc";

You'll have to take care with the way your modules are loaded to ensure proper ordering.

more info: (1, eval)('this') vs eval('this') in JavaScript?

Solution 3

You can use globalThis:

function test(h) {
    globalThis.testVar = h
}

test("This is a global var")
console.log(testVar)
Share:
26,722
Max Koretskyi
Author by

Max Koretskyi

Founder of inDepth.dev (@indepth_dev) community. Passionate about Mentorship, TechEd and WebDev. Angular & React contributor.

Updated on April 08, 2021

Comments

  • Max Koretskyi
    Max Koretskyi about 3 years

    I can't seem to find a description of the way I should export global variable from ES6 module. Is there a resource where it's defined?

    The only solution that seems to work is referencing a global object, like window:

    window['v'] = 3;
    

    But what if this scripts runs in Node.js? Then I don't have window; I have global. But this code is not good:

    var g = window || global;
    g['v'] = 3;
    

    I understand the concept of modules and don't use globals in my applications. However, having global variables during debugging in the console may be beneficial, especially when using bundlers like Webpack instead of loaders like SystemJs where you can easily import a module in a console.

  • Chris C
    Chris C about 4 years
    <3 Me: oh wow ES6 modules came out. Step 1) how do I declare a global variable. ES6: not allowed. Let me get this straight. Vanilla JS: allowed. ES6: Not. ES6: If we gave you global variables all the miscreants would couple all their code together like spaghetti. Me: What if you're an FP software architect that knows better? ES6: middle finger. Seriously? Their decision to not allow globals is as bad as C#'s prohibition of no static defs outside of classes and namespaces. I code generate. A lot. Importing everything is a no go. It's like an inductive proof with no base case. Depressing.
  • diachedelic
    diachedelic over 3 years
    @ChrisC I would like to see an example of a valid use case for global variables (thats variables, not constants). My understanding is that global variables are responsible for most of Javascript's security vulnerabilities.
  • Chris C
    Chris C over 3 years
    Let's say I have a service bus in module A. It has two methods bus.send(msg) and bus.receive(callback). Everywhere I use that bus, I need to import it. Could be hundreds of times. DRY tells us this is ridiculous. Useless noisy boilerplate. The security vulnerabilities don't come from global variables, they come from having them keyed as strings where anybody can muck with them willy nilly. If we had symbolic globals, where when I type "Bus" anywhere in MY modules I am referencing only my Bus definition and no other 3rdparty crap jammed into the global namespace it would work fine.
  • Chris C
    Chris C over 3 years
    module A: export global bus | module B: bus.Send("hi") | Basically the module system is just inserting an automatic import in each file that references bus. Not super controversial as far as I can tell...
  • Rich Remer
    Rich Remer over 3 years
    One area you commonly find globals in JavaScript is in test frameworks. The mocha library - for example - declares global functions "describe" and "it". It allows you to build a DSL-like language without muddling the code.
  • Lazerbeak12345
    Lazerbeak12345 about 2 years
    Here's a valid use case: detecting that you are not in a browser and behaving differently. This isn't modifying the global - but it still needs to read it to check for window. (then again, I'm still looking for another way, if it can be done)