关于javascript:在Node.js中的文件之间共享变量?

Share variables between files in Node.js?

以下是2个文件:

1
2
3
4
5
6
// main.js
require('./modules');
console.log(name); // prints"foobar"

// module.js
name ="foobar";

当我没有"var"的时候,它就工作了。但当我有:

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

名称将在main.js中未定义。

我听说全局变量不好,最好在引用之前使用"var"。但这是一个全局变量很好的例子吗?


全局变量几乎从来都不是一件好事(可能有一两个例外…)。在这种情况下,看起来您真的只是想导出"name"变量。例如。,

1
2
3
4
// module.js
var name ="foobar";
// export it
exports.name = name;

然后,在main.js中…

1
2
3
4
5
6
//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;


我找不到一个全局var是最佳选择的方案,当然您可以有一个,但请看一下这些例子,您可能会找到更好的方法来实现这一点:

场景1:将这些内容放入配置文件中

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

1
2
3
4
5
6
7
// File: config/environments/production.json
{
   "mailerType":"SMTP",
   "mailerConfig": {
     "service":"Gmail",
      ....
}

1
2
3
4
5
6
7
// File: config/environments/test.json
{
   "mailerType":"Stub",
   "mailerConfig": {
     "error": false
    }
}

(也为dev进行类似的配置)

要决定将加载哪个配置,请生成一个主配置文件(该文件将在整个应用程序中使用)

1
2
3
4
5
// File: config/config.js
var _ = require('underscore');

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

现在你可以得到这样的数据:

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

场景2:使用常量文件

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

用这个方法

1
2
3
4
5
6
7
8
9
// 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:使用helper函数获取/设置数据

这不是一个大粉丝,但至少你可以跟踪"名字"的使用(引用操作的例子)并进行验证。

1
2
3
4
5
6
7
8
9
10
11
12
// 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;
};

并使用它

1
2
3
4
5
6
7
8
// 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(就像我之前的某个时候一样),请尝试组织您在那里处理数据的方式,因为它会变得非常混乱。


如果需要共享多个变量,请使用以下格式

1
2
3
4
5
6
7
8
9
10
//module.js
   let name='foobar';
   let city='xyz';
   let company='companyName';

   module.exports={
    name,
    city,
    company
  }

用法

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


更新

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

1
2
3
4
5
6
7
8
9
10
// myModule.js
var shared = null;

function init(obj){
    shared = obj;
}

module.exports = {
    init:init
}

.

1
2
3
4
// main.js
var myModule = require('./myModule.js');
var shares = {value:123};
myModule.init(shares);

旧答案

要在模块之间共享变量,可以使用函数在主模块和模块之间获取变量的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//myModule.js
var mainFunction = null; //You can also put function reference in a Object or Array

function functionProxy(func){
    mainFunction = func; //Save the function reference
}

// --- Usage ---
// setTimeout(function(){
//   console.log(mainFunction('myString'));
//   console.log(mainFunction('myNumber'));
// }, 3000);

module.exports = {
    functionProxy:functionProxy
}

.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//main.js
var myModule = require('./myModule.js');
var myString ="heyy";
var myNumber = 12345;

function internalVariable(select){
    if(select=='myString') return myString;
    else if(select=='myNumber') return myNumber;
    else return null;
}

myModule.functionProxy(internalVariable);


// --- If you like to be able to set the variable too ---
// function internalVariable(select, set){
//    if(select=='myString'){
//        if(set!=undefined) myString = set;
//        else return myString;
//    }
//    else if(select=='myNumber'){
//      if(set!=undefined) myNumber = set;
//      else return myNumber;
//    }
//    else return null;
// }

您总是可以从main.js中获取值,即使该值已更改。


如果您要将代码发布到npm中,我认为使用不同的观点,global变量可能是最佳选择,因为您不能确定所有包都使用相同版本的代码。因此,如果您使用一个文件来导出一个singleton对象,它将在这里引起问题。

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

如果有更好的解决方案,请告诉我。


使用或不使用var关键字声明的变量已附加到全局对象。这是通过声明不带var关键字的变量在节点中创建全局变量的基础。而用var关键字声明的变量仍然是模块的本地变量。

请参阅本文了解更多信息-https://www.hacksparrow.com/global-variables-in-node-js.html