How do you share constants in NodeJS modules?

前端 未结 13 1433
庸人自扰
庸人自扰 2020-12-12 08:56

Currently I\'m doing this:

foo.js

const FOO = 5;

module.exports = {
    FOO: FOO
};

And using it in bar.js:<

相关标签:
13条回答
  • 2020-12-12 09:01

    Since Node.js is using the CommonJS patterns, you can only share variables between modules with module.exports or by setting a global var like you would in the browser, but instead of using window you use global.your_var = value;.

    0 讨论(0)
  • 2020-12-12 09:04

    I recommend doing it with webpack (assumes you're using webpack).

    Defining constants is as simple as setting the webpack config file:

    var webpack = require('webpack');
    module.exports = {
        plugins: [
            new webpack.DefinePlugin({
                'APP_ENV': '"dev"',
                'process.env': {
                    'NODE_ENV': '"development"'
                }
            })
        ],    
    };
    

    This way you define them outside your source, and they will be available in all your files.

    0 讨论(0)
  • 2020-12-12 09:06

    I don't think is a good practice to invade the GLOBAL space from modules, but in scenarios where could be strictly necessary to implement it:

    Object.defineProperty(global,'MYCONSTANT',{value:'foo',writable:false,configurable:false});
    

    It has to be considered the impact of this resource. Without proper naming of those constants, the risk of OVERWRITTING already defined global variables, is something real.

    0 讨论(0)
  • 2020-12-12 09:12

    Technically, const is not part of the ECMAScript specification. Also, using the "CommonJS Module" pattern you've noted, you can change the value of that "constant" since it's now just an object property. (not sure if that'll cascade any changes to other scripts that require the same module, but it's possible)

    To get a real constant that you can also share, check out Object.create, Object.defineProperty, and Object.defineProperties. If you set writable: false, then the value in your "constant" cannot be modified. :)

    It's a little verbose, (but even that can be changed with a little JS) but you should only need to do it once for your module of constants. Using these methods, any attribute that you leave out defaults to false. (as opposed to defining properties via assignment, which defaults all the attributes to true)

    So, hypothetically, you could just set value and enumerable, leaving out writable and configurable since they'll default to false, I've just included them for clarity.

    Update - I've create a new module (node-constants) with helper functions for this very use-case.

    constants.js -- Good

    Object.defineProperty(exports, "PI", {
        value:        3.14,
        enumerable:   true,
        writable:     false,
        configurable: false
    });
    

    constants.js -- Better

    function define(name, value) {
        Object.defineProperty(exports, name, {
            value:      value,
            enumerable: true
        });
    }
    
    define("PI", 3.14);
    

    script.js

    var constants = require("./constants");
    
    console.log(constants.PI); // 3.14
    constants.PI = 5;
    console.log(constants.PI); // still 3.14
    
    0 讨论(0)
  • 2020-12-12 09:13

    You can explicitly export it to the global scope with global.FOO = 5. Then you simply need to require the file, and not even save your return value.

    But really, you shouldn't do that. Keeping things properly encapsulated is a good thing. You have the right idea already, so keep doing what you're doing.

    0 讨论(0)
  • 2020-12-12 09:13

    I ended up doing this by exporting a frozen object with anonymous getter functions, rather than the constants themselves. This reduces the risk of nasty bugs introduced due to a simple typo of the const name, as a runtime error will be thrown in case of a typo. Here's a full example that also uses ES6 Symbols for the constants, ensuring uniqueness, and ES6 arrow functions. Would appreciate feedback if anything in this approach seems problematic.

    'use strict';
    const DIRECTORY = Symbol('the directory of all sheets');
    const SHEET = Symbol('an individual sheet');
    const COMPOSER = Symbol('the sheet composer');
    
    module.exports = Object.freeze({
      getDirectory: () => DIRECTORY,
      getSheet: () => SHEET,
      getComposer: () => COMPOSER
    });
    
    0 讨论(0)
提交回复
热议问题