Node.js内のファイル間で変数を共有しますか?


126

ここに2つのファイルがあります:

// main.js
require('./modules');
console.log(name); // prints "foobar"

// module.js
name = "foobar";

「var」がない場合は機能します。しかし、私が持っているとき:

// module.js
var name = "foobar";

名前はmain.jsでは未定義になります。

グローバル変数は良くないので、参照の前に "var"を使用する方がいいと聞きました。しかし、これはグローバル変数が良いケースですか?

回答:


184

グローバル変数は、ほとんど決して良いことではありません(例外が1つまたは2つあるかもしれません...)。この場合、「name」変数をエクスポートしたいだけのようです。例えば、

// module.js
var name = "foobar";
// export it
exports.name = name;

次に、main.jsで...

//main.js
// get a reference to your required module
var myModule = require('./module');

// name is a member of myModule due to the export above
var name = myModule.name;

1
グローバル変数は悪いです-私は完全にそれに同意します。しかし、モジュールが変数に依存している可能性もあります。require関数を介してこの変数を他のjsファイルに渡す方法はありますか?
2013年

1
@ jjoe64私があなたの言っていることを理解していません。exportsオブジェクトを通じて、必要なあらゆる値を効果的に共有できます。
jmar777 2013年

7
OPは、変数をmain.jsで定義して、module.jsで使用できるかどうかを尋ねています。何度も何度も使用されるパスを定義するのと同じ要件があります。
DesignerMonkey

4
@Designermonkeyその場合、おそらく、指定されたファイルにrequire()できるこれらのタイプの値を持つ設定オブジェクトを用意する方が良いでしょう。あなたがするだけで好きな場所にglobal.foo = 'bar'アクセスできることに注意してくださいfoo...しかし、最初の答えで言ったように、それはほとんど決して良いことではありません。
jmar777

そのおかげで、私はそれを行う方法を理解しました。私が正しいアイデアを持っていることを確認してくれてありがとう:)
DesignerMonkey

37

グローバルvarが最良の選択肢であるシナリオを見つけることはできませんが、もちろん1つはありますが、これらの例を確認すると、同じことを達成するためのより良い方法が見つかる場合があります。

シナリオ1:構成ファイルにデータを配置する

アプリケーション全体で同じである値が必要ですが、環境(本番、開発、またはテスト)、例としてメーラータイプによって異なります。

// File: config/environments/production.json
{
    "mailerType": "SMTP",
    "mailerConfig": {
      "service": "Gmail",
      ....
}

そして

// File: config/environments/test.json
{
    "mailerType": "Stub",
    "mailerConfig": {
      "error": false
    }
}

(開発用にも同様の設定を行います)

ロードする構成を決定するには、メイン構成ファイルを作成します(これはアプリケーション全体で使用されます)

// File: config/config.js
var _ = require('underscore');

module.exports = _.extend(
    require(__dirname + '/../config/environments/' + process.env.NODE_ENV + '.json') || {});

そして今、あなたはこのようなデータを得ることができます

// File: server.js
...
var config = require('./config/config');
...
mailer.setTransport(nodemailer.createTransport(config.mailerType, config.mailerConfig));

シナリオ2:定数ファイルを使用する

// File: constants.js
module.exports = {
  appName: 'My neat app',
  currentAPIVersion: 3
};

そして、それをこのように使用します

// File: config/routes.js

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

module.exports = function(app, passport, auth) {
  var apiroot = '/api/v' + constants.currentAPIVersion;
...
  app.post(apiroot + '/users', users.create);
...

シナリオ3:ヘルパー関数を使用してデータを取得/設定する

これの大ファンではありませんが、少なくとも「名前」(OPの例を引用)の使用を追跡し、検証を行うことができます。

// File: helpers/nameHelper.js

var _name = 'I shall not be null'

exports.getName = function() {
  return _name;
};

exports.setName = function(name) {
  //validate the name...
  _name = name;
};

そしてそれを使う

// File: controllers/users.js

var nameHelper = require('../helpers/nameHelper.js');

exports.create = function(req, res, next) {
  var user = new User();
  user.name = req.body.name || nameHelper.getName();
  ...

グローバルを使用する以外に解決策がない場合の使用例も考えられvarますが、node.jsを使用し始めた場合(以前のように)、通常はこれらのシナリオのいずれかを使用してアプリのデータを共有できます。そこにあるデータを処理する方法を整理します。


シナリオ2は気に入ったが、ビルドについて話し合った後でこれらの値を変更できるか?ほとんどの場合、npm run buildを実行します。または、ビルド後に値を変更できる方法を知っていますか?
Kashif Ullah 2018

@KashifUllah提供された情報だけでコメントに答えられるかどうかわからない場合は、サイトに新しい質問を追加できます
Felipe Pereira

16

複数の変数を共有する必要がある場合は、以下の形式を使用します

//module.js
   let name='foobar';
   let city='xyz';
   let company='companyName';

   module.exports={
    name,
    city,
    company
  }

使用法

  // main.js
    require('./modules');
    console.log(name); // print 'foobar'

2
最初の場所で発生する可能性のある混乱を省くための簡単なメモ:module.exportsを使用する必要があります!jsファイルが何と呼ばれても(例:global.js)。moduleはグローバルスコープに存在するノードオブジェクトです![global.js内ではmodule.exports = .....を使用します]
Mohamed Allal 2018

それは成功あなたは「聞かせて」削除された場合、およびする必要はありません「module.exportsはは..」
アフマドZahabi

6

共有する変数を1つのオブジェクトとして保存します。次に、読み込まれたモジュールに渡して、オブジェクト参照を通じて変数にアクセスできるようにします。

// main.js
var myModule = require('./module.js');
var shares = {value:123};

// Initialize module and pass the shareable object
myModule.init(shares);

// The value was changed from init2 on the other file
console.log(shares.value); // 789

他のファイルで。

// module.js
var shared = null;

function init2(){
    console.log(shared.value); // 123
    shared.value = 789;
}

module.exports = {
    init:function(obj){
        // Save the shared object on current module
        shared = obj;

        // Call something outside
        init2();
    }
}

1

varキーワードを使用して、または使用せずに宣言された変数が、グローバルオブジェクトにアタッチされました。これは、varキーワードなしで変数を宣言することにより、Nodeでグローバル変数を作成するための基礎です。varキーワードで宣言された変数は、モジュールに対してローカルのままです。

詳細については、この記事を参照してください-https://www.hacksparrow.com/global-variables-in-node-js.html


3
これらの断片は矛盾していますか?1)「varキーワードの有無にかかわらず宣言された変数がグローバルオブジェクトにアタッチされました。」2)「varキーワードで宣言された変数は、モジュールに対してローカルのままです。」
BaldEagle 2017

1

別の見方globalをすると、コードをに公開する場合は、変数が最良の選択npmであると思います。すべてのパッケージが同じリリースのコードを使用しているとは限らないからです。したがって、singletonオブジェクトのエクスポートにファイルを使用すると、ここで問題が発生します。

globalrequire.mainまたはファイル間で共有されるその他のオブジェクトを選択できます。

より良い解決策があるかどうか教えてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.