在 Node.js 文件之间共享变量?

这里有两个文件:

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


// module.js
name = "foobar";

当我没有“ var”的时候,它会工作,但是当我有:

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

Name 将在 main.js 中未定义。

我听说全局变量是不好的,你最好在引用之前使用“ var”。但在这种情况下,全局变量是好的吗?

283428 次浏览

全局变量 差不多从来不是一件好事(也许有一两个例外... ...)。在这种情况下,看起来您真的只想导出您的“ 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;

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

有关进一步理解,请参阅本文 -https://www.hacksparrow.com/global-variables-in-node-js.html

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

// 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();
}
}

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

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

我无法找到一个场景,其中一个全球 var是最好的选择,当然你可以有一个,但看看这些例子,你可能会找到一个更好的方法来实现同样的:

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

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

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

还有

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

(也为 dev 做一个类似的配置)

要决定加载哪个配置,可以创建一个主配置文件(这个文件将在整个应用程序中使用)

// 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: 使用 helper 函数获取/设置数据

虽然不是很喜欢这个,但是至少您可以跟踪“ name”的使用(引用 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 (就像我以前一样)尝试组织你在那里处理数据的方式,因为它会很快变得混乱。

我有不同的看法,我认为 global变量可能是最好的选择,如果你要发布你的代码到 npm,因为你不能确定所有的包都使用相同的发布你的代码。因此,如果您使用一个文件来导出 singleton对象,那么这里就会出现问题。

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

否则,将包作为可选的依赖项包安装可以避免此问题。

请告诉我是否有更好的解决办法。

不是一个新的方法,但有点优化。创建一个包含全局变量的文件,并通过 exportrequire共享它们。在本例中,Getter 和 Setter 更加动态,全局变量可以是只读的。要定义更多的全局变量,只需将它们添加到 globals对象。

Global.js

const globals = {
myGlobal: {
value: 'can be anytype: String, Array, Object, ...'
},
aReadonlyGlobal: {
value: 'this value is readonly',
protected: true
},
dbConnection: {
value: 'mongoClient.db("database")'
},
myHelperFunction: {
value: function() { console.log('do help') }
},
}


exports.get = function(global) {
// return variable or false if not exists
return globals[global] && globals[global].value ? globals[global].value : false;
};


exports.set = function(global, value) {
// exists and is protected: return false
if (globals[global] && globals[global].protected && globals[global].protected === true)
return false;
// set global and return true
globals[global] = { value: value };
return true;
};

要在其他文件中获取和设置的示例

const globals = require('./globals');


console.log(globals.get('myGlobal'));
// output: can be anytype: String, Array, Object, ...


globals.get('myHelperFunction')();
// output: do help


let myHelperFunction = globals.get('myHelperFunction');
myHelperFunction();
// output: do help


console.log(globals.set('myGlobal', 'my new value'));
// output: true
console.log(globals.get('myGlobal'));
// output: my new value


console.log(globals.set('aReadonlyGlobal', 'this shall not work'));
// output: false
console.log(globals.get('aReadonlyGlobal'));
// output: this value is readonly


console.log(globals.get('notExistingGlobal'));
// output: false

如果目标是浏览器(通过 Parcel.js 或类似的方式捆绑 Node 代码) ,那么只需在 window对象上设置属性,它们就会变成全局变量:

window.variableToMakeGlobal = value;

然后,您可以从所有模块(更一般地说,从任何 Javascript 上下文)访问这个变量。