目前我正在做这个:

foo.js

const FOO = 5;

module.exports = {
    FOO: FOO
};

并在bar.js中使用它:

var foo = require('foo');
foo.FOO; // 5

还有更好的办法吗?在exports对象中声明常量会让人感到尴尬。


当前回答

从之前的项目经验来看,这是一个很好的方法:

在constants.js中:

// constants.js

'use strict';

let constants = {
    key1: "value1",
    key2: "value2",
    key3: {
        subkey1: "subvalue1",
        subkey2: "subvalue2"
    }
};

module.exports =
        Object.freeze(constants); // freeze prevents changes by users

在main.js(或app.js等)中,使用如下:

// main.js

let constants = require('./constants');

console.log(constants.key1);

console.dir(constants.key3);

其他回答

我建议使用webpack(假设你正在使用webpack)。

定义常量就像设置webpack配置文件一样简单:

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

通过这种方式,您可以在源代码之外定义它们,并且它们将在您的所有文件中可用。

您可以使用global显式地将其导出到全局作用域。Foo = 5。然后,您只需请求该文件,甚至不保存返回值。

但说真的,你不应该这么做。保持适当的封装是一件好事。你已经有了正确的想法,所以继续做你正在做的事情。

最后,我导出了一个带有匿名getter函数的冻结对象,而不是导出常量本身。这降低了由于简单的const名称输入错误而引入的严重错误的风险,因为在输入错误的情况下将抛出运行时错误。下面是一个完整的例子,它也使用ES6符号作为常量,确保唯一性,以及ES6箭头函数。如果在这种方法中有任何问题,将感激反馈。

'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
});

从技术上讲,const不是ECMAScript规范的一部分。此外,使用你已经注意到的“CommonJS Module”模式,你可以改变这个“常量”的值,因为它现在只是一个对象属性。(不确定这是否会级联需要相同模块的其他脚本的任何更改,但这是可能的)

要获得一个可以共享的真实常数,请检查Object。create、Object.defineProperty和Object.defineProperties。如果你设置writable: false,那么你的“常量”中的值不能被修改。:)

这有点啰嗦(但即使是这样也可以用一个小JS来改变),但你应该只需要为你的常量模块做一次。使用这些方法,您省略的任何属性都会默认为false。(与通过赋值定义属性相反,赋值默认所有属性为true)

所以,假设,你可以只设置value和enumerable,省略writable和可配置的,因为它们默认为false,我只是为了清晰起见才包含它们。

更新-我已经为这个用例创建了一个带有helper函数的新模块(node-constants)。

js——很好

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

js——更好

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

作为一种替代方法,您可以将“常量”值分组在一个局部对象中,并导出一个返回该对象的浅克隆的函数。

var constants = { FOO: "foo" }

module.exports = function() {
  return Object.assign({}, constants)
}

然后,如果有人重新分配FOO就无关紧要了,因为它只会影响他们的本地副本。