在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”。但这是全局变量很好的情况吗?

Answers:


184

全局变量几乎从来都不是一件好事(也许有两个例外……)。在这种情况下,您似乎真的只想导出“名称”变量。例如,

// 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文件?
appsthatmatter 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:将内容放入配置文件

您需要一些在整个应用程序中都相同的值,但是它会根据环境(生产,开发或测试),邮件程序类型(例如)而变化,您需要:

// 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运行build。还是您知道构建后可以更改值的某种方法?
卡西夫·乌拉

@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)。模块是存在于全局范围内的节点对象![因此在global.js中,我们使用module.exports = .....]
Mohamed Allal

如果删除“ let”,它将成功,并且不需要“ module.exports ..”
Ahmad Zahabi

6

将任何要共享的变量保存为一个对象。然后将其传递给加载的模块,以便它可以通过对象引用访问变量。

// 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关键字或不使用var关键字声明的变量都附加到全局对象。” 和2)“使用var关键字声明的变量在模块中保持本地。”
BaldEagle

1

换种说法,我认为global如果要将代码发布到npm,则变量可能是最佳选择,因为您不能确定所有软件包都使用相同版本的代码。因此,如果您使用文件导出singleton对象,则会在此处引起问题。

您可以选择globalrequire.main或在文件之间共享的任何其他对象。

请告诉我是否有更好的解决方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.