在Node.js中有没有办法从必需的模块访问父项的变量范围?

时间:2015-04-29 11:59:15

标签: javascript node.js singleton

对于我的项目,我有很多函数对单个全局变量进行更改,但由于文件非常大,我想将这些函数拆分为不同的模块。但是,在传递全局变量时,它会创建另一个实例。有没有办法防止这种情况?

例如,这是所需的输出:

var global_var=1;

function first_function(){
    console.log(++global_var);
}

function second_function(){
    console.log(++global_var);  
}

first_function(); //outputs 2
second_function(); //outputs 3
first_function(); //outputs 4

但是当试图将first_function和second_function分成不同的模块时,

//in main.js file
var global_var=1;

var first_function=require(./first_function)(global_var);
var second_function=require(./second_function)(global_var);

first_function(); //outputs 2
second_function(); //outputs 2
first_function(); //outputs 2

//in first_function.js and second_function.js
module.exports=function(global_var){

    return ++global_var;

}

每次我想进行函数调用时,我都不想重新分配或重新传输global_var,因为函数调用每分钟更改global_var数千次,而global_var是一个超过1000个键的对象。

有没有办法确保子模块正在修改全局对象的同一个实例而不传递它?

3 个答案:

答案 0 :(得分:3)

如果那个代码(在我猜的例子中简化了)做了你说的话,我会感到非常惊讶。这样:

var first_function=require(./first_function)(global_var);

global_var(顺便说一下,不是全局的,因为它是用var定义的)传递给导出的函数。导出的函数返回该值递增1。所以当你打电话时:

first_function();

实际上你应该得到一个数字不是函数的错误。

有很多方法可以解决这个问题。由于您的变量是一个对象,因此无论在何处使用它都可以通过 reference 获得,这意味着更新一个实例应该全部更新它们。

解决方案1:使first_function.js导出一个返回函数的函数。

//in first_function.js and second_function.js
module.exports=function(global_var){
  // This function will be the value of "first_function"
  // when you require it and pass in "global_var"
  return function() {
    return ++global_var;
  };
};

解决方案2:使用实际全局变量。

global.someVar = 1;

// first_function.js
module.exports = function() {
  return ++global.someVar;
};

这里需要注意的是,全局变量通常被认为是代码气味(不良实践)。

解决方案3:使变量成为文件的导出。通过引用再次缓存导出,因此需要该变量的每个文件都将获得相同的引用。

// global_var.js
exports.global_var = 1;

// first_function.js
var glob = require('./global_var');
module.exports = function() {
  return ++glob.global_var;
};

答案 1 :(得分:0)

如果你声明变量没有var,它将从任何模块中看到,但这是一个不好的做法,因为这个变量也会影响所有模块:

global_var=1;

var first_function=require(./first_function);
var second_function=require(./second_function);

first_function(); //outputs 2
second_function(); //outputs 3
first_function(); //outputs 4

//in first_function.js and second_function.js
module.exports=function(){

    return ++global_var;

}

答案 2 :(得分:0)

如vanadium23所述,这可以使用全局变量来完成。 这是一个非常糟糕的主意。模块模式被设计为默认包含模块内的代码,并通过导出使某些部分可访问。

解决此问题的一种方法是传递非基元(基本上是对象)。如前所述,原始类型将作为副本传递,而不是引用。传递对象将确保所需的模块可以更改其字段。

<强>增量-value.js:

module.exports = function(object) { object.value++; };

<强> main.js:

var myObject = { value: 0 };
var incrementValue = require('./increment-value');
incrementValue(myObject);
console.log(myObject); // { value: 1 }