wake-up-neo.net

Wie teilt man Konstanten in NodeJS-Modulen?

Derzeit mache ich das:

foo.js

const FOO = 5;

module.exports = {
    FOO: FOO
};

Und benutze es in bar.js:

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

Gibt es einen besseren Weg, dies zu tun? Es ist unangenehm, die Konstante im Objekt exports zu deklarieren.

203
Tower

Sie können es mit global.FOO = 5 Explizit in den globalen Bereich exportieren. Dann müssen Sie lediglich die Datei anfordern und nicht einmal Ihren Rückgabewert speichern.

Aber wirklich, das solltest du nicht tun. Es ist eine gute Sache, die Dinge richtig gekapselt zu halten. Sie haben bereits die richtige Idee, machen Sie also weiter, was Sie tun.

80
Alex Wayne

Meiner Meinung nach benutze ich Object.freeze ermöglicht einen trockeneren und aussagekräftigeren Stil. Mein bevorzugtes Muster ist:

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

Veraltete Leistungswarnung

Das folgende Problem wurde in Version 8 im Januar 2014 behoben und ist für die meisten Entwickler nicht mehr relevant:

Beachten Sie, dass sowohl das Setzen von "Beschreibbar" auf "Falsch" als auch das Verwenden von Object.freeze in Version 8 - https://bugs.chromium.org/p/v8/issues/detail?id=1858 und erhebliche Leistungseinbußen nach sich ziehen http://jsperf.com/performance-frozen-object

254
Spain Train

Technisch gesehen ist const nicht Teil der ECMAScript-Spezifikation. Außerdem können Sie mit dem von Ihnen notierten "CommonJS Module" -Muster den Wert dieser "Konstante" ändern, da es sich jetzt nur noch um eine Objekteigenschaft handelt. (Ich bin mir nicht sicher, ob dies Änderungen an anderen Skripten nach sich zieht, die dasselbe Modul erfordern, aber es ist möglich)

Um eine echte Konstante zu erhalten, die Sie auch teilen können, lesen Sie Object.create , Object.defineProperty und Object.defineProperties . Wenn Sie writable: false, dann kann der Wert in Ihrer "Konstante" nicht geändert werden. :)

Es ist ein wenig ausführlich (aber auch das kann mit ein wenig JS geändert werden), aber Sie sollten es nur einmal für Ihr Konstantenmodul tun müssen. Bei Verwendung dieser Methoden ist jedes Attribut, das Sie auslassen, standardmäßig false. (Im Gegensatz zur Definition von Eigenschaften über Zuweisung, bei der alle Attribute standardmäßig auf true gesetzt werden)

Hypothetisch könnten Sie also einfach value und enumerable setzen und writable und configurable weglassen, da sie standardmäßig false sind. Ich habe sie nur zur Verdeutlichung eingefügt.

Update - Für diesen Anwendungsfall habe ich ein neues Modul ( Knoten-Konstanten ) mit Hilfsfunktionen erstellt.

constants.js - Gut

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

constants.js - Besser

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
157
Dominic Barnes

ES6 Weg.

Export in foo.js

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

Import in bar.js

const {FOO} = require('foo');
76
Diego Mello

Ich fand die von Dominic vorgeschlagene Lösung die beste, aber es fehlt immer noch ein Merkmal der "const" -Deklaration. Wenn Sie in JS eine Konstante mit dem Schlüsselwort "const" deklarieren, wird das Vorhandensein der Konstante zur Analysezeit und nicht zur Laufzeit überprüft. Wenn Sie also den Namen der Konstante irgendwo später im Code falsch geschrieben haben, erhalten Sie eine Fehlermeldung, wenn Sie versuchen, Ihr node.js-Programm zu starten. Welches ist eine weitaus bessere Rechtschreibprüfung.

Wenn Sie die Konstante mit der Funktion define () wie von Dominic vorgeschlagen definieren, wird keine Fehlermeldung angezeigt, wenn Sie die Konstante falsch geschrieben haben, und der Wert der falsch geschriebenen Konstante ist undefiniert (was zum Debuggen von Kopfschmerzen führen kann).

Aber ich denke, das ist das Beste, was wir bekommen können.

Außerdem gibt es in constans.js eine Art Verbesserung der Dominic-Funktion:

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;

Auf diese Weise können Sie die Funktion define () in anderen Modulen verwenden und Konstanten sowohl im Modul constants.js als auch in Ihrem Modul, von dem aus Sie die Funktion aufgerufen haben, definieren. Das Deklarieren von Modulkonstanten kann dann auf zwei Arten erfolgen (in script.js).

Zuerst:

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

Zweite:

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

Wenn Sie möchten, dass die Funktion define () nur aus dem Konstantenmodul aufgerufen wird (um das globale Objekt nicht aufzublähen), definieren Sie sie auch folgendermaßen in constants.js:

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

und benutze es wie folgt in script.js:

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

Aus früheren Projekterfahrungen ist dies ein guter Weg:

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

Verwenden Sie in main.js (oder app.js usw.) Folgendes:

// main.js

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

console.log(constants.key1);

console.dir(constants.key3);

Ich denke, dass const das Problem für die meisten Leute löst, die nach dieser Antwort suchen. Wenn Sie wirklich eine unveränderliche Konstante brauchen, schauen Sie sich die anderen Antworten an. Um alles zu organisieren, speichere ich alle Konstanten in einem Ordner und benötige dann den gesamten Ordner.

src/main.js Datei

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. hier werden die deal und note auf der main.js erste Ebene sein

src/consts_folder/note.js

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

Ps. obj wird auf der main.js die zweite Ebene sein

src/consts_folder/deal.js

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

Ps. str wird auf der main.js die zweite Ebene sein

Endergebnis in der Datei main.js:

console.log(constants.deal); Ausgabe:

{deal: {str: 'Ich bin ein Deal-String'},

console.log(constants.note); Ausgabe:

note: {obj: {type: 'object', description: 'Ich bin ein Notizobjekt'}}

5
Luis Martins

import und export (wahrscheinlich brauche ich ab 2018 so etwas wie babel, um importieren zu können)

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

4
orangesherbert

Alternativ können Sie Ihre "konstanten" Werte in einem lokalen Objekt gruppieren und eine Funktion exportieren, die einen flachen Klon dieses Objekts zurückgibt.

var constants = { FOO: "foo" }

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

Dann ist es egal, ob jemand FOO neu zuweist, da dies nur die lokale Kopie betrifft.

3
herman

Da Node.js die CommonJS-Muster verwendet, können Sie Variablen zwischen Modulen nur mit module.exports Oder durch Festlegen einer globalen Variable wie im Browser gemeinsam nutzen. Statt des Fensters verwenden Sie jedoch global.your_var = value;. .

2
alessioalex

Am Ende habe ich ein eingefrorenes Objekt mit anonymen Getter-Funktionen exportiert und nicht die Konstanten selbst. Dies reduziert das Risiko von bösen Fehlern, die durch einen einfachen Tippfehler des Konstantennamens verursacht werden, da im Fall eines Tippfehlers ein Laufzeitfehler ausgegeben wird. Hier ist ein vollständiges Beispiel, in dem auch ES6-Symbole für die Konstanten verwendet werden, um die Eindeutigkeit zu gewährleisten, sowie ES6-Pfeilfunktionen. Würde mich über Feedback freuen, wenn irgendetwas in diesem Ansatz problematisch erscheint.

'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
});
1
Eloquence

Ich halte es nicht für eine gute Praxis, den GLOBAL-Space von Modulen aus zu erobern, aber in Szenarien, in denen dies unbedingt erforderlich sein könnte:

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

Es muss die Auswirkung dieser Ressource berücksichtigt werden. Ohne die ordnungsgemäße Benennung dieser Konstanten ist das Risiko des Überschreibens bereits definierter globaler Variablen real.

0
colxi

Ich empfehle es mit Webpack (setzt voraus, dass Sie Webpack verwenden).

Das Definieren von Konstanten ist so einfach wie das Festlegen der Webpack-Konfigurationsdatei:

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

Auf diese Weise definieren Sie sie außerhalb Ihrer Quelle und sie sind in allen Ihren Dateien verfügbar.

0
galki