Global context being affected by array function .replace

Hello all,

I am having an issue in a function node. I have stored previously the array [" 10"," 11"," 12"," 13"," 14"," 15"] in the global variable "destinations".

The code in the function is as follows:

var array = global.get("destinations");
for(i=0; i < array.length; i++){ // Go through all the array
    array[i] = array[i].replace(/ /g, ''); //Remove all the leading spaces that were already there (/ /g searches in all the string)
    }
msg.payload = array;
return msg;

The issue that I have is that when the instruction array[i] = array[i].replace(/ /g, ''); gets executed, for some reason it stores the new value in the global context "destinations" though I never execute any instruction like context.set.

How is that possible? Could it be a bug? Thanks!

This is because you are handling a pointer to the context variable and not a copy so this will effect the origin.
You will need to clone the variable to manipulate it without doing it.
Fortunately Nodered has a deep cloning function build into to the function nodes by default. Its documented here:

https://nodered.org/docs/api/modules/v/0.20.0/@node-red_util_util.html#.cloneMessage
Edit:
Forgot an example.
It can be accessed in a function node by using something like this:

var origin = global.get("origin");
var copy =  RED.util.cloneMessage(origin);
1 Like

Ahh that is why!

If I understood correctly then, instead of var array = global.get("destinations"); it should be var array = cloneMessage(global.get("destinations"));?

Does this also would mean that array = "hello" would be the same as global.set("destinations", "hello") in this case?

Thank you very much!

I edited the post above with an example of the correct syntax. I think nodered utilizes lodash behind the scenes to do this:

To answer your second question:

Effectively yes although I think it’s good practice to call the set function anyway but I don’t thinks it’s strictly always necessary.
But not using the set method can of course also give you problems. For example if the global variable is not yet initialized and you do something like this:

var hello = global.get("hello") || "hello";
hello = "hello_test";

hello will get initialized to the string and you can change it within the function node but it will not be pointing at or initialize in global context so you would have to use set in this case.
So to prevent edge cases like this it’s better to use set anyway.

1 Like

Actually, no - in this particular case, that is not how it would work.

If you start with:

var array = global.get("destinations");

then, as has been said, array is a pointer to the object held in context.

If you do an operation on that object, it modifies array and the object in context.

However, if you do:

array = "hello"

then you are not changing the object in context - you are changing what thing the array variable points at. So doing that type of reassignment wouldn't do anything to the object in context.

1 Like

Also mentioned here for additional reference: