如何在 NodeJS 模块中共享常量?

2022-08-30 00:04:02

目前我正在这样做:

哎呀.js

const FOO = 5;

module.exports = {
    FOO: FOO
};

并将其用于:bar.js

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

有没有更好的方法来做到这一点?在导出对象中声明常量感觉很尴尬。


答案 1

在我看来,利用Object.freeze允许DRYer和更多的声明性风格。我的首选模式是:

./lib/constants.js

module.exports = Object.freeze({
    MY_CONSTANT: 'some value',
    ANOTHER_CONSTANT: 'another value'
});

./lib/some-module.js

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

console.log(constants.MY_CONSTANT); // 'some value'

constants.MY_CONSTANT = 'some other value';

console.log(constants.MY_CONSTANT); // 'some value'

过时的性能警告

以下问题已于 2014 年 1 月在 v8 中修复,并且不再与大多数开发人员相关:

请注意,将可写设置为 false 和使用 Object.freeze 都会在 v8 中造成巨大的性能损失 - https://bugs.chromium.org/p/v8/issues/detail?id=1858https://jsben.ch/AhAVa


答案 2

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

要获得也可以共享的真实常量,请查看 Object.createObject.definePropertyObject.defineProperties。如果设置 ,则无法修改“常量”中的值。:)writable: false

它有点冗长,(但即使这样也可以用一点JS来改变),但你只需要为常量模块做一次。使用这些方法,您遗漏的任何属性都默认为 。(与通过赋值定义属性相反,赋值将所有特性默认为falsetrue)

所以,假设,你可以只设置和,省略,因为它们会默认为,我只是将它们包括在内以方便起见。valueenumerablewritableconfigurablefalse

更新 - 我为这个用例创建了一个带有帮助器函数的新模块(节点常量)。

常量.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);

脚本.js

var constants = require("./constants");

console.log(constants.PI); // 3.14
constants.PI = 5;
console.log(constants.PI); // still 3.14