आप NodeJS मॉड्यूल में स्थिरांक कैसे साझा करते हैं?


239

वर्तमान में मैं यह कर रहा हूं:

foo.js

const FOO = 5;

module.exports = {
    FOO: FOO
};

और में इसका उपयोग bar.js:

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

क्या ऐसा करने के लिए इससे अच्छा तरीका है? निर्यात वस्तु में स्थिर घोषित करना अजीब लगता है।


6
यदि आप इसे निर्यात करना चाहते हैं, तो आप इसे डालते हैं exports। इसके बारे में अजीब क्या है?
एलेक्स वेन

5
मैं C # और PHP का उपयोग कर रहा हूँ। मुझे लगता है कि मुझे बस प्रत्येक स्थिर को दो बार परिभाषित करने की आदत डालनी होगी। शायद भविष्य में हमारे पास होगा export const FOO = 5;
टॉवर

1
@ भविष्य अब (ES2015) है! 2ality.com/2014/09/…
स्पेन ट्रेन

1
क्या यह क्रियात्मक रूप से अधिक संक्षिप्त से अलग है module.exports={FOO:5};?
जो लैप

3
यह केवल अक्वर्ड महसूस नहीं करता है, यह अब कोई स्थिर नहीं है
इनी

जवाबों:


96

आप इसे स्पष्ट रूप से वैश्विक दायरे में निर्यात कर सकते हैं global.FOO = 5। फिर आपको बस फ़ाइल की आवश्यकता है, और अपना रिटर्न मान भी नहीं बचाएं।

लेकिन वास्तव में, आपको ऐसा नहीं करना चाहिए। चीजों को ठीक से एनकैप्सुलेट करना अच्छी बात है। आपके पास पहले से ही सही विचार है, इसलिए आप जो कर रहे हैं उसे करते रहें।


51
मुझे यह करने के लिए खेद है, लेकिन बेहतर जानने के लिए -1 लेकिन वैकल्पिक (बेहतर) समाधान प्रदान नहीं करना; (पुन: "लेकिन वास्तव में, आपको ऐसा नहीं करना चाहिए। चीजों को ठीक से एनकैप्सुलेट करना एक अच्छी बात है।")
धन्यवाद

22
अगर पूरे सॉफ्टवेयर डेवलपमेंट समुदाय ने इस तरह सोचा, तो हम अभी भी पंचर का उपयोग कर रहे हैं। सौभाग्य से वहाँ बाहर कुछ mavericks हैं जो जानते हैं कि जब हम अपने आप पर लगाए गए पागल नियमों को तोड़ने के लिए बेहतर है। यदि एनकैप्सुलेशन उपयोगी है, तो इसका उपयोग करें। यदि यह एक नर्वस नानी है जो आपको अपना काम करने से रोक रही है, तो नर्वस नानी को आग दें और उसके साथ आगे बढ़ें।
unsynchronized

22
@naomik (सुपर लेट रिप्लाई टाइम) वास्तविक कारण जो मैंने बेहतर समाधान नहीं दिया, वह यह है कि ओपी पहले से ही समाधान जानता है। अपने स्वयं के मॉड्यूल में चीजों को इनकैप्सुलेट करें और जहां आवश्यक हो, उनकी आवश्यकता है।
एलेक्स वेन

1
फिर यह एक वास्तविक जवाब नहीं है और आपको "आप काफी अच्छा कर रहे हैं, विकल्प बुरे हैं" बताते हुए एक स्पष्टीकरण टिप्पणी होनी चाहिए ..
एंड्री पोपोव

1
एन्कैप्सुलेशन का गलत अनुप्रयोग। जब कोई वर्ग विशेष मानों को संकेतक के रूप में उपयोग करता है और उन्हें एक नाम देता है, तो आप उसे किसी भी कोड के साथ साझा करना चाहते हैं जो उस वर्ग का उपयोग करता है।
अनुदान

314

मेरी राय में, उपयोग 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 में v8 में तय की गई थी और अब अधिकांश डेवलपर्स के लिए प्रासंगिक नहीं है:

विदित हो कि झूठा लिखने के लिए और ऑब्जेक्ट का उपयोग करने के लिए दोनों का उपयोग करना। v8 में v8 का भारी प्रदर्शन है - https://bugs.chromium.org/p/v8/issues/detail?id=1858 और http://jsperf.com / प्रदर्शन-जमी-वस्तु


4
Object.freeze के लिए अच्छा उपयोग मामला!
एस्टुस फ्लास्क

यदि मुझे निरंतर और कार्यों दोनों को निर्यात करने की आवश्यकता है तो यह कैसा दिखना चाहिए? क्या मुझे फ्रीज ब्लॉक में भी कार्य करना चाहिए?
टॉम

3
यह दृष्टिकोण बेहतर है क्योंकि आईडीई स्वत: पूर्ण इसके साथ काम करता है।
डेविड ए

3
यह एक शानदार उत्तर है, लेकिन यह अंत में v8 के प्रदर्शन के बारे में पुरानी चेतावनी के कारण लोगों को इस दृष्टिकोण से दूर कर सकता है। कृपया चेतावनी को हटाने पर विचार करें।
संपतश्री

4
धन्यवाद @ क्रामिया! मैंने इसे अपडेट कर दिया है, लेकिन केवल ऐतिहासिक संदर्भ के लिए मूल चेतावनी पाठ छोड़ दिया है (और क्योंकि इनमें से कुछ टिप्पणियां इसके बिना समझ में नहीं आएंगी)।
स्पेन ट्रेन

163

तकनीकी constरूप से, ECMAScript विनिर्देश का हिस्सा नहीं है। इसके अलावा, आपके द्वारा नोट किए गए "कॉमनजस मॉड्यूल" पैटर्न का उपयोग करके, आप उस "स्थिर" के मूल्य को बदल सकते हैं क्योंकि यह अब केवल एक वस्तु संपत्ति है। (निश्चित नहीं है कि यदि यह अन्य लिपियों में किसी भी बदलाव के लिए एक ही मॉड्यूल की आवश्यकता है, लेकिन यह संभव है)

आप भी साझा कर सकते हैं कि बाहर की जाँच एक असली लगातार प्राप्त करने के लिए 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

2
@AntoineHedgecock यह आवश्यक नहीं है, पर दस्तावेज़ की जाँच करें Object.defineProperty()। निर्दिष्ट सभी गुण falseइस संदर्भ में ग्रहण नहीं किए गए हैं ।
डोमिनिक बार्न्स

6
इसके अलावा ध्यान देने योग्य बात, ऑब्जेक्ट.फ्रीज ()
डेमियनब

1
यह इस सवाल का सबसे अच्छा जवाब है। +1। अगर मैं कर सकता तो मैं इसे और बढ़ा दूंगा।
रयान

1
अद्भुत जवाब, एक बहुत ही सुरुचिपूर्ण और सुरक्षित समाधान।
एलेक्स

1
@SpainTrain यह प्रतीत होता है कि codereview.chromium.org/135903014
Grinde

100

ईएस 6 रास्ता।

foo.js में निर्यात

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

bar.js में आयात

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

40
हाँ। स्टैक ओवरफ्लो को पुराने उत्तरों को ह्रास करने का एक तरीका चाहिए।
रिक जॉली

7
नोट यह है कि constमें bar.jsहै कि लागू करता है destructured चर के अचल स्थिति, नहीं constमें foo.js। है यही कारण है, एक का उपयोग कर सकते हैं let {FOO} =में bar.jsऔर "निरंतर" चर उत्परिवर्तित। AFAIK, निर्यात की अपरिवर्तनीयता को लागू करने के लिए, अभी भी ES मॉड्यूल की जरूरत है या Object.freeze
स्पेन ट्रेन

एक भी FOOअंदर बदल सकता है foo.js
lima_fil

16

मैंने पाया कि डोमिनिक ने जिस समाधान का सुझाव दिया था वह सबसे अच्छा था, लेकिन यह अभी भी "कॉन्स्ट" घोषणा की एक विशेषता को याद करता है। जब आप JS में "const" कीवर्ड के साथ एक कॉन्स्टेंट की घोषणा करते हैं, तो स्थिरांक का अस्तित्व पार्स समय पर चेक किया जाता है, रनटाइम पर नहीं। इसलिए यदि आपने अपने कोड में बाद में कहीं स्थिरांक का नाम गलत लिखा है, तो आपको अपना नोड शुरू करने का प्रयास करते समय एक त्रुटि मिलेगी। जो कहीं अधिक बेहतर गलत वर्तनी की जाँच है।

यदि आप परिभाषित के साथ निरंतर परिभाषित करते हैं () फ़ंक्शन जैसे डोमिनिक ने सुझाव दिया है, तो आपको त्रुटि नहीं मिलेगी यदि आपने निरंतर को गलत वर्तनी दी है, और गलत वर्तनी वाले मान का मान अपरिभाषित हो जाएगा (जिससे डीबगिंग सिरदर्द हो सकता है)।

लेकिन मुझे लगता है कि यह सबसे अच्छा हम प्राप्त कर सकते हैं।

इसके अतिरिक्त, यहाँ 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;

इस तरह आप अन्य मॉड्यूल में डिफाइन () फंक्शन का उपयोग कर सकते हैं, और यह आपको कॉन्स्टैंटों.जैस मॉड्यूल और कॉन्सटेंट दोनों को अपने मॉड्यूल के अंदर परिभाषित करने की अनुमति देता है जिससे आपने फंक्शन को बुलाया। मॉड्यूल स्थिरांक की घोषणा तब दो तरीकों से (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

इसके अलावा, यदि आप चाहते हैं कि परिभाषित () फ़ंक्शन केवल स्थिरांक मॉड्यूल से बुलाया जाए (वैश्विक ऑब्जेक्ट को ब्लोट नहीं करना), तो आप इसे इस तरह परिभाषित करते हैं जैसे कि constants.js:

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

और इसे script.js में इस तरह उपयोग करें:

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

11

पिछले परियोजना के अनुभव से, यह एक अच्छा तरीका है:

स्थिरांक में। 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);

8

मुझे लगता है कि constइस anwwer की तलाश में ज्यादातर लोगों के लिए समस्या हल करती है। यदि आपको वास्तव में अपरिवर्तनीय स्थिरांक की आवश्यकता है, तो अन्य उत्तरों को देखें। सब कुछ व्यवस्थित रखने के लिए मैं एक फ़ोल्डर पर सभी स्थिरांक सहेजता हूं और फिर पूरे फ़ोल्डर की आवश्यकता होती है।

src / main.js फ़ाइल

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। यहाँ dealऔर notemain.js पर पहला स्तर होगा

src / consts_folder / note.js

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

Ps। objmain.js पर दूसरा स्तर होगा

src / consts_folder / deal.js

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

Ps। strmain.js पर दूसरा स्तर होगा

Main.js फ़ाइल पर अंतिम परिणाम:

console.log(constants.deal); ouput:

{सौदा: {str: 'I \' मा सौदा स्ट्रिंग '},

console.log(constants.note); ouput:

नोट: {obj: {प्रकार: 'ऑब्जेक्ट', विवरण: 'I \' मा नोट ऑब्जेक्ट '}}



4

एक विकल्प के रूप में, आप अपने "स्थिर" मानों को स्थानीय ऑब्जेक्ट में समूहित कर सकते हैं, और एक फ़ंक्शन निर्यात कर सकते हैं जो इस ऑब्जेक्ट का एक उथला क्लोन लौटाता है।

var constants = { FOO: "foo" }

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

तब कोई फर्क नहीं पड़ता कि कोई FOO को पुन: असाइन करता है क्योंकि यह केवल उनकी स्थानीय प्रति को प्रभावित करेगा।


या सिर्फ मॉड्यूल .exports = () => ({FOO: "फू", BAR: "बार"});
ब्योर्न ग्रैम्बो

3

चूंकि Node.js CommonJS पैटर्न का उपयोग कर रहा है, आप केवल वैरिएबल के साथ module.exportsया जैसे आप वैरिएबल में ग्लोबल वैर सेट करके मॉड्यूल के बीच वेरिएबल साझा कर सकते हैं , लेकिन इसके बजाय आप जिस विंडो का उपयोग करते हैं global.your_var = value;


2

मैं खुद को स्थिरांक के बजाय गुमनाम गटर कार्यों के साथ एक जमी हुई वस्तु का निर्यात करके ऐसा कर रहा हूं। यह कॉस्ट नाम के एक सरल टाइपो के कारण शुरू किए गए गंदा कीड़े के जोखिम को कम करता है, क्योंकि टाइपो के मामले में एक रनटाइम त्रुटि डाली जाएगी। यहां एक पूर्ण उदाहरण है जो स्थिरांक के लिए 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
});

0

मैं इसे वेबपैक के साथ करने की सलाह देता हूं (यह मानता है कि आप वेबपैक का उपयोग कर रहे हैं)।

स्थिरांक को परिभाषित करना वेबपैक कॉन्फिगर फाइल को सेट करने जितना आसान है:

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

इस तरह आप उन्हें अपने स्रोत के बाहर परिभाषित करते हैं, और वे आपकी सभी फाइलों में उपलब्ध होंगे।


0

मुझे नहीं लगता कि मॉड्यूल से वैश्विक अंतरिक्ष पर आक्रमण करने के लिए एक अच्छा अभ्यास है, लेकिन परिदृश्यों में जहां इसे लागू करने के लिए कड़ाई से आवश्यक हो सकता है:

Object.defineProperty(global,'MYCONSTANT',{value:'foo',writable:false,configurable:false});

इसे इस संसाधन का प्रभाव माना जाना चाहिए। उन स्थिरांक के सही नामकरण के बिना, OVERWRITTING का जोखिम पहले से ही परिभाषित वैश्विक चर है, कुछ वास्तविक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.