Currently I'm doing this:
foo.js
const FOO = 5;
module.exports = {
FOO: FOO
};
And using it in bar.js
:
var foo = require('foo');
foo.FOO; // 5
Is there a better way to do this? It feels awkward to declare the constant in the exports object.
When you declare a constant in JS with the "const" keyword, the existence of the constant is checked at parse time, not at runtime. So if you misspelled the name of the constant somewhere later in your code, you'll get an error when you try to start your node. js program.
The curly braces around the variable name is called Destructuring assignment, and const {PI} = Math; will translate to const PI = Math.PI.
export const is a named export that exports a const declaration or declarations. To emphasize: what matters here is the export keyword as const is used to declare a const declaration or declarations. export may also be applied to other declarations such as class or function declarations.
In my opinion, utilizing Object.freeze
allows for a DRYer and more declarative style. My preferred pattern is:
./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'
The following issue was fixed in v8 in Jan 2014 and is no longer relevant to most developers:
Be aware that both setting writable to false and using Object.freeze have a massive performance penalty in v8 - https://bugs.chromium.org/p/v8/issues/detail?id=1858 and https://jsben.ch/AhAVa
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.
Object.defineProperty(exports, "PI", {
value: 3.14,
enumerable: true,
writable: false,
configurable: false
});
function define(name, value) {
Object.defineProperty(exports, name, {
value: value,
enumerable: true
});
}
define("PI", 3.14);
var constants = require("./constants");
console.log(constants.PI); // 3.14
constants.PI = 5;
console.log(constants.PI); // still 3.14
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With