Как вы делитесь константами в модулях NodeJS? - PullRequest
197 голосов
/ 21 декабря 2011

В настоящее время я делаю это:

foo.js

const FOO = 5;

module.exports = {
    FOO: FOO
};

И используя его в bar.js:

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

Есть ли лучший способ сделать это? Неловко объявлять константу в объекте экспорта.

Ответы [ 13 ]

245 голосов
/ 21 января 2014

На мой взгляд, использование Object.freeze позволяет использовать СУХОЙ и более декларативный стиль. Мой предпочтительный шаблон:

./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'

Предупреждение об устаревшей производительности

Следующая проблема была исправлена ​​в v8 в январе 2014 года и больше не актуальна для большинства разработчиков:

Имейте в виду, что как установка на запись в false, так и использование Object.freeze имеют серьезные потери производительности в v8 - https://bugs.chromium.org/p/v8/issues/detail?id=1858 и http://jsperf.com/performance-frozen-object

157 голосов
/ 22 декабря 2011

Технически, const не является частью спецификации ECMAScript.Кроме того, используя шаблон «CommonJS Module», который вы заметили, вы можете изменить значение этой «константы», поскольку теперь это просто свойство объекта.(не уверен, что это каскадно внесет какие-либо изменения в другие сценарии, для которых требуется тот же модуль, но это возможно)

Чтобы получить реальную константу, которой вы также можете поделиться, проверьте Object.create, Object.defineProperty и Object.defineProperties.Если вы установите writable: false, то значение в вашей «константе» не может быть изменено.:)

Это немного многословно (но даже это можно изменить с помощью небольшого JS), но вам нужно будет сделать это только один раз для вашего модуля констант.Используя эти методы, любой атрибут, который вы пропускаете, по умолчанию равен false.(в отличие от определения свойств посредством присваивания, в котором все атрибуты по умолчанию имеют значение true)

Таким образом, гипотетически, вы можете просто установить value и enumerable, оставив writable и configurableпоскольку по умолчанию они равны false, я просто включил их для ясности.

Обновление - Я создал новый модуль ( константы узла ) с вспомогательными функциями для этого самого варианта использования.

constants.js - Хорошо

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

constants.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
76 голосов
/ 21 декабря 2011

Вы можете явно экспортировать его в глобальную область с помощью global.FOO = 5. Тогда вам просто нужно запросить файл и даже не сохранять возвращаемое значение.

Но на самом деле, вы не должны этого делать. Правильно хранить вещи в инкапсуляции. У вас уже есть правильная идея, поэтому продолжайте делать то, что делаете.

73 голосов
/ 08 сентября 2016

ES6 way.

экспорт в foo.js

const FOO = 'bar';
module.exports = {
  FOO
}

импорт в bar.js

const {FOO} = require('foo');
15 голосов
/ 16 февраля 2012

Я нашел решение, предложенное Домиником, лучшим, но в нем все еще отсутствует одна особенность декларации "const". Когда вы объявляете константу в JS с ключевым словом «const», существование константы проверяется во время разбора, а не во время выполнения. Поэтому, если вы ошиблись в названии константы где-то позже в своем коде, вы получите сообщение об ошибке при попытке запустить программу node.js. Что намного лучше, чем проверка орфографии.

Если вы определили константу с помощью функции define (), как предложил Доминик, вы не получите ошибку, если вы неправильно определили константу, и значение константы с орфографической ошибкой будет неопределенным (что может привести к отладке головной боли).

Но я думаю, это лучшее, что мы можем получить.

Кроме того, вот что-то вроде улучшения функции Доминика в constans.js:

global.define = function ( name, value, exportsObject )
{
    if ( !exportsObject )
    {
        if ( exports.exportsObject )
            exportsObject = exports.exportsObject;
        else 
            exportsObject = exports;        
    }

    Object.defineProperty( exportsObject, name, {
        'value': value,
        'enumerable': true,
        'writable': false,
    });
}

exports.exportObject = null;

Таким образом, вы можете использовать функцию define () в других модулях, и она позволяет вам определять константы как внутри модуля constants.js, так и констант внутри вашего модуля, из которого вы вызвали функцию. Объявление констант модуля можно сделать двумя способами (в script.js).

Первый:

require( './constants.js' );

define( 'SOME_LOCAL_CONSTANT', "const value 1", this ); // constant in script.js
define( 'SOME_OTHER_LOCAL_CONSTANT', "const value 2", this ); // constant in script.js

define( 'CONSTANT_IN_CONSTANTS_MODULE', "const value x" ); // this is a constant in constants.js module

Во-вторых:

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

// More convenient for setting a lot of constants inside the module
constants.exportsObject = this;
define( 'SOME_CONSTANT', "const value 1" ); // constant in script.js
define( 'SOME_OTHER_CONSTANT', "const value 2" ); // constant in script.js

Кроме того, если вы хотите, чтобы функция define () была вызвана только из модуля констант (не для раздувания глобального объекта), вы определите ее следующим образом в constants.js:

exports.define = function ( name, value, exportsObject )

и используйте его так в script.js:

constants.define( 'SOME_CONSTANT', "const value 1" );
7 голосов
/ 14 августа 2017

Из предыдущего опыта проекта это хороший способ:

В 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);
5 голосов
/ 08 февраля 2018

Я думаю, что const решает проблему для большинства людей, которые ищут этот ответ. Если вам действительно нужна неизменная константа, посмотрите на другие ответы. Чтобы все было организовано, я сохраняю все константы в папке, а затем требую всю папку.

src / main.js file

const constants = require("./consts_folder");

ЦСИ / consts_folder / index.js

const deal = require("./deal.js")
const note = require("./note.js")


module.exports = {
  deal,
  note
}

Ps. здесь deal и note будут первым уровнем на main.js

ЦСИ / consts_folder / note.js

exports.obj = {
  type: "object",
  description: "I'm a note object"
}

Ps. obj будет вторым уровнем на main.js

ЦСИ / consts_folder / deal.js

exports.str = "I'm a deal string"

Ps. str будет вторым уровнем на main.js

Окончательный результат в файле main.js:

console.log(constants.deal); Ouput:

{сделка: {str: 'Я строка сделки'},

console.log(constants.note); Ouput:

примечание: {obj: {тип: 'объект', описание: 'Я объект примечания'}}

4 голосов
/ 01 февраля 2018

import и export (возможно, для импорта требуется что-то вроде babel с 2018 года)

types.js

export const BLUE = 'BLUE'
export const RED = 'RED'

myApp.js

import * as types from './types.js'

const MyApp = () => {
  let colour = types.RED
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

3 голосов
/ 23 июня 2016

В качестве альтернативы вы можете сгруппировать свои «постоянные» значения в локальном объекте и экспортировать функцию, которая возвращает поверхностный клон этого объекта.

var constants = { FOO: "foo" }

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

Тогда не имеет значения, если кто-то переназначит FOO, потому что это повлияет только на их локальную копию.

2 голосов
/ 22 декабря 2011

Поскольку Node.js использует шаблоны CommonJS, вы можете обмениваться переменными между модулями только с module.exports или установив глобальную переменную, как в браузере, но вместо окна вы используете global.your_var = value;.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...