Programing

NodeJS 모듈에서 상수를 어떻게 공유합니까?

lottogame 2020. 5. 1. 07:59
반응형

NodeJS 모듈에서 상수를 어떻게 공유합니까?


현재 나는 이것을하고있다 :

foo.js

const FOO = 5;

module.exports = {
    FOO: FOO
};

그리고 그것을 사용 bar.js:

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

더 좋은 방법이 있습니까? 내보내기 객체에서 상수를 선언하는 것이 어색합니다.


을 사용하여 명시 적으로 전역 범위로 내보낼 수 있습니다 global.FOO = 5. 그런 다음 단순히 파일이 필요하고 반환 값을 저장하지 않아도됩니다.

그러나 실제로는 그렇게해서는 안됩니다. 제대로 캡슐화 된 상태를 유지하는 것이 좋습니다. 당신은 이미 올바른 생각을 가지고 있으므로, 당신이하고있는 일을 계속하십시오.


내 생각에, 활용 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=1858http://jsperf.com) 에서 큰 성능 저하가 발생합니다. / 성능 고정 개체


기술적으로 constECMAScript 사양의 일부가 아닙니다. 또한 앞서 언급 한 "CommonJS Module"패턴을 사용하여 이제 "일정한"값을 객체 속성으로 변경할 수 있습니다. (동일한 모듈이 필요한 다른 스크립트로 변경 사항을 캐스케이드할지 확실하지 않지만 가능합니다)

당신은 또한, 공유 체크 아웃 할 수있는 실제 상수 얻으려면 Object.create, Object.defineProperty등을 Object.defineProperties. 을 설정하면 writable: false"일정한"값을 수정할 수 없습니다. :)

조금 장황하지만 (작은 JS로 변경할 수도 있음) 상수 모듈에 대해 한 번만 수행하면됩니다. 이러한 방법을 사용하면 제외하는 모든 속성의 기본값은 false입니다. (할당을 통해 속성을 정의하는 것과 반대로, 모든 속성의 기본값은 true)

그래서, 가설, 당신은 단지 설정할 수 valueenumerable밖으로 떠나 writable그리고 configurable그들은 기본적 것이기 때문에 false, 난 그냥 명확성을 위해 그들을 포함 시켰습니다.

업데이트 -나는 매우 사용 사례에 대한 도우미 기능을 가진 새로운 모듈 ( node-constants )을 만들었습니다 .

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

ES6 방식.

foo.js로 내보내기

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

bar.js로 가져 오기

const {FOO} = require('foo');

I found the solution Dominic suggested to be the best one, but it still misses one feature of the "const" declaration. 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. Which is a far more better misspelling check.

If you define the constant with the define() function like Dominic suggested, you won't get an error if you misspelled the constant, and the value of the misspelled constant will be undefined (which can lead to debugging headaches).

But I guess this is the best we can get.

Additionally, here's a kind of improvement of Dominic's function, in 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;

In this way you can use the define() function in other modules, and it allows you to define constants both inside the constants.js module and constants inside your module from which you called the function. Declaring module constants can then be done in two ways (in script.js).

First:

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

Second:

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

Also, if you want the define() function to be called only from the constants module (not to bloat the global object), you define it like this in constants.js:

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

and use it like this in script.js:

constants.define( 'SOME_CONSTANT', "const value 1" );

From previous project experience, this is a good way:

In the 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

In main.js (or app.js, etc.), use it as below:

// main.js

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

console.log(constants.key1);

console.dir(constants.key3);

I think that const solves the problem for most people looking for this anwwer. If you really need an immutable constant, look into the other answers. To keep everything organized I save all constants on a folder and then require the whole folder.

src/main.js file

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

src/consts_folder/index.js

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


module.exports = {
  deal,
  note
}

Ps. here the deal and note will be first level on the main.js

src/consts_folder/note.js

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

Ps. obj will be second level on the main.js

src/consts_folder/deal.js

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

Ps. str will be second level on the main.js

Final result on main.js file:

console.log(constants.deal); Ouput:

{ deal: { str: 'I\'m a deal string' },

console.log(constants.note); Ouput:

note: { obj: { type: 'object', description: 'I\'m a note object' } }


import and export (prob need something like babel as of 2018 to use import)

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


As an alternative, you can group your "constant" values in a local object, and export a function that returns a shallow clone of this object.

var constants = { FOO: "foo" }

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

Then it doesn't matter if someone re-assigns FOO because it will only affect their local copy.


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;.


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

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.


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.

참고URL : https://stackoverflow.com/questions/8595509/how-do-you-share-constants-in-nodejs-modules

반응형