Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs closure variable not updated in module

I need some help understanding the NodeJs. I'm obviously missing something fundamental. I've got a module similar to the following, using a basic revealing module pattern...

var someArray = [];

var publicApi = {
    someArray: someArray,
    someFunction: someFunction
};

function someFunction() {
    someArray = ['blue', 'green'];
}

module.exports = publicApi;

When I consume this module, someArray is not changed when I call someFunction...

var myModule = require('myModule');

myModule.someFunction();
var test = myModule.someArray;
// test is always an empty array

Please help me understand why. I realize I can probably get this to work using a constructor, but I want to fill the gap in my knowledge of why the above does not work.

Update:

I can get this to work with the following modifications to the module...

var theModule = {
    someArray: [],
    someFunction: someFunction
};

function someFunction() {
    theModule.someArray = ['blue', 'green'];
}

module.exports = theModule;

but I'd still like to understand exactly why the code in the first module did not work. The module I'm working on is fine as a singleton, so I'd love to see what is considered best practice for having variables in a module that can be altered by the functions in that module, and be publicly accessible outside that module.

like image 851
Tim Hardy Avatar asked Nov 19 '15 15:11

Tim Hardy


1 Answers

The reason the first way you did it didn't work is the same reason it wouldn't work doing the same in JavaScript without Node:

var someArray = [];

var object = {
    someArray: someArray,
}
someArray = [1, 2, 3];
console.log(object.someArray);

This prints [] because object.someArray is a reference to the first array you created. This is the process:

var someArray = [];

Create an empty array and then save a reference to that array as the name someArray. Let's call this array1.

var object = {
    someArray: someArray
}

Create an object with a property someArray, make that property reference the array that someArray references. It's important to know that this means this reference is now a reference to array1, not to someArray. This leads us to:

someArray = [1, 2, 3];

Which creates a new array (let's call it array2), which it then stores as someArray. This array is completely independent of array1 and all future references of someArray will get array2, but it has no effect on previous access.

This works exactly the same as your Node example - when you overwrite someArray rather than publicApi.someArray, you make no changes to publicApi.someArray, so you can't expect it to be different.

To hopefully make this clear, you go from the following:

someArray -> array1[]
object.someArray -> array1[]

To this:

someArray -> array2[1, 2, 3]
object.someArray -> array1[]

Note that object.someArray is unchanged.

like image 159
Thor84no Avatar answered Sep 30 '22 07:09

Thor84no