Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Node.js is there a way to access the variable scope of the parent from a required module?

For my project, I have many functions make changes to a single global variable, but since the file is very big, i would like to split these functions into different modules. however, when passing the global variable, it creates another instance. is there a way to prevent this?

for example, this is the desired output:

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

but when trying to seperate first_function and second_function into different modules,

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

}

I don't want to reassign or re-transfer global_var everytime i want to make the function calls, since the function calls which change global_var are made thousands of times per minute and global_var is an object with over 1000 keys.

Is there a way to ensure that the child modules are modifying the same instance of the global object without passing it around?

like image 841
JasonY Avatar asked Apr 29 '15 11:04

JasonY


2 Answers

I would be really surprised if that code (simplified in the example I'm guessing) does what you say. This:

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

passes global_var (which isn't global by the way, as it's defined with var) in to the exported function. The exported function returns that value incremented by one. So when you call it:

first_function();

You should actually get an error that a number is not a function.

There are lots of ways to solve this problem. Since your variable is an object, it will be available by reference wherever it's used, meaning that updating one instance should update them all.

Solution 1: make first_function.js export a function that returns a function.

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

Solution 2: Use an actual global variable.

global.someVar = 1;

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

The caveat here is that global variables are typically considered a code smell (bad practice).

Solution 3: Make the variable an export of a file. Exports are cached, again by reference, so each file that requires that variable will get the same reference.

// global_var.js
exports.global_var = 1;

// first_function.js
var glob = require('./global_var');
module.exports = function() {
  return ++glob.global_var;
};
like image 195
tandrewnichols Avatar answered Sep 18 '22 16:09

tandrewnichols


If you declare variable without var it will be seen from any modules, but it's a bad practice because this variable will also affects all modules:

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;

}
like image 42
vanadium23 Avatar answered Sep 22 '22 16:09

vanadium23