# Global.get in a function changes the global variable

**URL:** <https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259>\
**Category:** General\
**Tags:** function-node\
**Created:** [28 November 2023 17:22 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259 "2023-11-28T17:22:03Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [28 November 2023 17:22 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/1 "2023-11-28T17:22:03Z")

</div>

This is strange. I got a list of my zigbee devices in an javascript array which are stored in `global.set("devices")`:

```auto
[
{"name":"Coordinator","status":"online","time":1701191747304,"color":"white","ignored":false,"alarm":false},
{"name": "device1".....}
]

```

I grab this table in a function in order to feed a HTML table to show status and time of last update in a easy to read form. Thus:

```auto
var dlist = global.get("devices")
for (const d of dlist) {
    node.warn(d);
    // loop over objects in dlist
    var tstamp = new Date(d.time)
    var tstring = tstamp.toLocaleString('de-DE')
    d.time = tstring;
    d.color = "white"
    if (d.status == "offline") {
        d.color = "red"
    }
}
msg.payload = dlist
return msg

```

As you can see there is no `global.set` function called. Nevertheless when runnning the function the global variable `devices` is changed. The time stamp is now a string.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [28 November 2023 17:29 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/2 "2023-11-28T17:29:08Z")

</div>

> [@haegar33](#):
>
> As you can see there is no `global.set` function called. Nevertheless when runnning the function the global variable `devices` is changed.

This is a very common question but quite difficult to search in the forum but the closest search term I think would be "by reference"

In short, when you store an object in JavaScript, you are NOT storing a copy, you are storing a pointer aka "by reference"

So when you modify the object you are modifying the same thing that is stored in context.

The solution is to ensure you store (or retrieve) an actual copy not a pointer.

For this, you can use `RED.util.cloneMessage`

e.g.

```auto
const dlist = RED.util.cloneMessage(global.get("devices"))

```

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [28 November 2023 17:40 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/3 "2023-11-28T17:40:03Z")

</div>

I already thought about a "by reference" issue. Actuall this is the first time I want a function to get a global variable and modify it.  
I tried the `RED.util.cloneMessage` function but it throws an array in the loop:

```auto
for (const d of dlist) 
var dlist: object

Type 'object' must have a '[Symbol.iterator]()' method that returns an iterator.(2488)

```

as suddenly `dlist`is no longer an array but an object.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [28 November 2023 17:56 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/4 "2023-11-28T17:56:47Z")

</div>

Can you show your full function code (since you updated it) and a screenshot of the object/array in the "Context viewer" (on the side bar)

Additionally, add

```auto
// DISABLE cloning const dlist = RED.util...
var dlist = global.get("devices") // revert temporarily
// ADD THIS 👇
node.warn({ dlist, "type": typeof dlist, proto: dlist.constructor?.name })
// ADD THIS 👆
for (const d of dlist) {
    node.warn(d);
    // ...
    // ...
}

```

and show me what you see in the debug panel when the function runs

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [29 November 2023 08:55 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/5 "2023-11-29T08:55:21Z")

</div>

Ok that's interesting:  
The global variable `devices` is an array of objects (filled by another function)  
Getting the content into `dlist` results in an object with one array!  
Node.warn output:

```auto
{"dlist":
[{"name":"Coordinator","status":"online","time":1701193123007,"color":"white","ignored":false,"alarm":false}],
"type":"object",
"proto":"Array"}

```

Extracting array elements in a loop gives each element as an object:

```auto
for (const d of dlist) {
    node.warn(d);.....

```

gives:

```auto
{"name":"Coordinator","status":"online","time":1701193123007,"color":"white","ignored":false,"alarm":false}

```

Now I am confused 😉

---

<div class="post-metadata">

**Author:** ![ralphwetzel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ralphwetzel/32/53713_2.png) [@ralphwetzel](https://discourse.nodered.org/u/ralphwetzel)\
**Post date:** [29 November 2023 09:00 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/6 "2023-11-29T09:00:44Z")

</div>

> [@haegar33](#):
>
> Getting the content into `dlist` results in an _ **object with one array** _!

Not really. You posted an **array with one object**! Thus the extract is correct:

```auto
{
    "dlist": [
        {
            "name": "Coordinator",
            "status": "online",
            "time": 1701193123007,
            "color": "white",
            "ignored": false,
            "alarm": false
        }
    ],
    "type": "object",
    "proto": "Array"
}

```

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [29 November 2023 09:14 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/7 "2023-11-29T09:14:31Z")

</div>

> [@ralphwetzel](#):
>
> Not really. You posted an **array with one object**!

Please look at my first posting. That is the content of the global variable `devices`  
And that is array of objects.

In practice it would not really matter as long as I can loop over this array to modify each object in `dlist` and return an output array without modifying the global variable

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [29 November 2023 09:21 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/8 "2023-11-29T09:21:25Z")

</div>

> [@Steve-Mcl](#):
>
> The solution is to ensure you store (or retrieve) an actual copy not a pointer.
> 
> For this, you can use `RED.util.cloneMessage`

Actually this works now! The javascript editor still reports the error message (see above) but the function returns the desired array and **does not** modify the global variable!

Thanks!

---

<div class="post-metadata">

**Author:** ![ralphwetzel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/ralphwetzel/32/53713_2.png) [@ralphwetzel](https://discourse.nodered.org/u/ralphwetzel)\
**Post date:** [29 November 2023 09:28 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/9 "2023-11-29T09:28:28Z")

</div>

```javascript
let dlist = global.get("devices")
let result = []; // <== create a new array for results
for (const d of dlist) {
    let dd = RED.util.cloneMessage(d); // <== clone the current object
    node.warn(dd);
    // loop over objects in dlist
    let tstamp = new Date(dd.time); // <== begin to modify the newly created object
    let tstring = tstamp.toLocaleString('de-DE');
    dd.time = tstring;
    dd.color = "white";
    if (dd.status == "offline") {
        dd.color = "red";
    }
    result.push(dd); // <== push the modified object to the results array
}
msg.payload = result; // <== forward the results of your operation
return msg

```

---

<div class="post-metadata">

**Author:** ![haegar33](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haegar33/32/38805_2.png) [@haegar33](https://discourse.nodered.org/u/haegar33)\
**Post date:** [29 November 2023 12:54 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/10 "2023-11-29T12:54:36Z")

</div>

Thanks! That code is straightforward and avoids the error message.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [13 December 2023 12:55 UTC](https://discourse.nodered.org/t/global-get-in-a-function-changes-the-global-variable/83259/11 "2023-12-13T12:55:19Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
