# Error in a function in Node-Re 2.2 not present in previous versoins

**URL:** <https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357>\
**Category:** General\
**Created:** [27 January 2022 17:42 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357 "2022-01-27T17:42:53Z")\
**Posts on this page:** 17\
**Page:** 3

<div class="post-metadata">

**Author:** ![scargill](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/scargill/32/1118_2.png) [@scargill](https://discourse.nodered.org/u/scargill)\
**Post date:** [29 January 2022 08:58 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/41 "2022-01-29T08:58:58Z")

</div>

Thanks for that early-morning response Nick (assuming you're in GMT+0 timezone or similar). I'm actually quite excited abuoit the changes in V2.2 and being made aware of the context data tab which somehow I'd missed. what was all that about with the brackets on your first line..

Ok, I'm happy with

```auto
let timing = RED.util.cloneMessage(global.get("timing"))

```

for a clone assuming it's scope is the local function?

And am I right in saying that to refer to the actual global I can do:

```auto
let timing=global.get("timing");

```

again local to my function?  
in which case I stupidly then went on to update the global when I could have referred to timing= [blah,blah];

all ok?

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [29 January 2022 09:34 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/42 "2022-01-29T09:34:55Z")

</div>

When you change the global you should still do `global.set()` at some point in the function so that node-red knows you have changed it. In fact it is not necessary when using in-memory context, but if you are using file storage the the `set` function tells node red that it needs to write it out to disc at the appropriate moment. Otherwise your change might not persist over a restart.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [29 January 2022 14:23 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/43 "2022-01-29T14:23:13Z")

</div>

> [@scargill](#):
>
> for a clone assuming it's scope is the local function?

Yes, that's correct. Cloning JavaScript objects can be a bit of an art as you get into shallow and deep clones 🙂 Mostly you don't need to worry and can simple use the nice shortcut function that Node-RED provides.

> [@scargill](#):
>
> var timing

What I meant by my earlier comment was that the word "timing" (which, by the way, even you mistyped as "timeing" - something that I might also do and indicates maybe not a good word to use as a var name) is very generic. something like `myThingsTiming` - e.g. `temperatureSensorTiming` or whatever - is a much better name for a variable, especially one that you have made global since in a few months time you will likely scratch your head for several minutes wondering what the real scope of that variable is.

> [@scargill](#):
>
> what was all that about with the brackets on your first line..

That is a shortcut to creating a clone of an array. Using the spread operator `...` to "spread" the elements of the source array into a new array defined as `[]`.

---

<div class="post-metadata">

**Author:** ![GeorgeCastanza](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/georgecastanza/32/40766_2.png) [@GeorgeCastanza](https://discourse.nodered.org/u/GeorgeCastanza)\
**Post date:** [30 January 2022 10:25 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/44 "2022-01-30T10:25:22Z")

</div>

What's wrong with var?

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [30 January 2022 10:34 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/45 "2022-01-30T10:34:22Z")

</div>

There are plenty of discussions around `var`/`let`/`const` available online. Some people get very passionate about it. Ultimately it comes down to scope - just how visible a `var` variable is compared to `let`. Rather than repeat all the discussion points, here's a good article that explains the difference.

> **[Var, Let, and Const – What's the Difference?](https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/)**
>
> A lot of shiny new features came out with ES2015 (ES6). And now, since it's 2020, it's assumed that a lot of JavaScript developers have become familiar with and have started using these features. While this assumption might be partially true, it's...

---

<div class="post-metadata">

**Author:** ![scargill](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/scargill/32/1118_2.png) [@scargill](https://discourse.nodered.org/u/scargill)\
**Post date:** [30 January 2022 10:50 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/46 "2022-01-30T10:50:28Z")

</div>

Ah, but. that article makes the scopes clear but doesn't seem to cover the use of LET when referring to an existing global variable. If I'm right we just agreed that unlike var it becomes a reference to the original var unless we specifically refer to it as a clone - but that take me back to another language that used to give me problems,

SO in the case of my badly named global array `timing`, if I want to be lazy in it's use I can say:  
`let timing=global.get("timing")`  
and I'll be working on the original. But does that only refer to strings and arrays - what about numbers?  
`let mynumber=global.get("mynumber")`  
Same?

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [30 January 2022 11:03 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/47 "2022-01-30T11:03:17Z")

</div>

It only applies to Arrays and Objects.

Strings, Numbers and Booleans can be changed locally without modifying the global.

Consider this code:

```auto
let myArray = [1, 2, 3]

```

This will create a new Array object in memory and `myArray` will be a pointer to it in memory.

If you do operations that modify the contents of the array such as:

```auto
myArray[1] = 4
myArray.push(1)

```

then you are modifying the array held in memory.

But if you do:

```auto
let myArray = [1, 2, 3]
myArray = [2, 3, 4]

```

then you are creating a _new_ array object in memory and changing what `myArray` points to. This is a reassignment - it does not change the original array.

Now lets consider strings, numbers and booleans,

```auto
let myString = "foo"

```

Strings, numbers and booleans are called immutable types. They cannot be changed. Any operation you do on a variable of that type will _reassign_ the variable to point to the new value. When you do something like:

```auto
myString = myString + " bar"

```

You are reassigning `myString` to point to a different String value. The original string `foo` has not been changed.

* * *

This all applies to working with context in Node-RED.

```auto
let timing = global.get("timing")

```

Is creating a locally scoped variable pointing to the value of the global context value.

If it is an Array or Object and you modify the contents of that object, you modify the value in context.  
If it is a String, Number or Boolean and you change its value, you are reassigning what the local variable points at and the context value is untouched.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [30 January 2022 11:17 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/48 "2022-01-30T11:17:39Z")

</div>

> [@scargill](#):
>
> If I'm right we just agreed that unlike var it becomes a reference to the original var unless we specifically refer to it as a clone

There is no difference between let and var for that. The difference is purely in the scoping.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [30 January 2022 12:12 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/49 "2022-01-30T12:12:37Z")

</div>

JavaScript is rather like playing the guitar - deceptively "simple"! 🕶

---

<div class="post-metadata">

**Author:** ![scargill](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/scargill/32/1118_2.png) [@scargill](https://discourse.nodered.org/u/scargill)\
**Post date:** [30 January 2022 13:17 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/50 "2022-01-30T13:17:44Z")

</div>

Ok, now you've got me pondering whether to take up tree felling - this is getting too complicated. "To LET or not to LET.... whether 'tis nobler..... etc".. the word CONTEXT is driving me nuts.

So in short I AM modifying my original array - BUT - I have to poke in "global.set() anyway at some point.

"Is creating a locally scoped variable pointing to the value of the global context value."

That make it sound like updating for example "timing[4]+=56;" is initially reading the global but is not actually updating the global......

Yup, - tree-felling has to be easier. I'd just go and experiment but if I screw it up I could end up freezing to death 🙂

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [30 January 2022 13:30 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/51 "2022-01-30T13:30:52Z")

</div>

> [@scargill](#):
>
> So in short I AM modifying my original array - BUT - I have to poke in "global.set() anyway at some point.

Yes.

You might like to consider a pattern that I often use, which is to group all related context data into one object. Then in the function node I would have something like

```auto
let data = global.get("data")
...
if (data.someVar == ...)
...
data.someVar = someNewValue
...
global.set(data)
return msg

```

So I start the function with a get(), use the variable as I go along, then right at the end global.set() it again.  
The only time this might involve some overheads is if the data does not usually change within the flush period specified for the context, and file based context is in use. The not-required call of global.set() is not itself an issue as the overhead in that is trivial, but if using file based context then this will (I think) force a write to the file system at whatever rate is specified in settings.js (or the default value). However, even the overhead of writing it out every few minutes is likely to be negligible.

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [30 January 2022 13:33 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/52 "2022-01-30T13:33:57Z")

</div>

> [@scargill](#):
>
> That make it sound like updating for example "timing[4]+=56;" is initially reading the global but is not actually updating the global......

No. That is updating the global. It is not changing what `timing` points at. It is changing the value inside the array that `timing` points at.

---

<div class="post-metadata">

**Author:** ![scargill](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/scargill/32/1118_2.png) [@scargill](https://discourse.nodered.org/u/scargill)\
**Post date:** [30 January 2022 14:26 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/53 "2022-01-30T14:26:37Z")

</div>

Thanks for this Nick - but reading back over this lot has just opened up another can of worms - COLIN uses and example`global.set()` and elsewhere has used `global.set(data)`.

I was only aware of `global.set("x",y);` or `global.set("x","y") ;` where the value is a string. yet here I'm seeing `global.set(data)` with no value and no quotes around `data` and `global.set()` with not even an object or array etc. Was I supposed to take these literally?

---

<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:** [30 January 2022 14:33 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/54 "2022-01-30T14:33:17Z")

</div>

When Colin's said use `global.set()` ...

> [@Colin](#):
>
> When you change the global you should still do `global.set()`

... it was only to inform you that it should be called (with your values) to ensure file context is written.

To be more explicit, you never just call `global.set()`, you would actually call `global.set("timing", timing)` to cause any changes to be written to file

---

<div class="post-metadata">

**Author:** ![scargill](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/scargill/32/1118_2.png) [@scargill](https://discourse.nodered.org/u/scargill)\
**Post date:** [30 January 2022 15:02 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/55 "2022-01-30T15:02:03Z")

</div>

Thank you - another of life's mysteries solved. That's how I thought it worked... so I still have to treat `let timing=global.get("timing")` as if it were a copy then - if not there would be no need for `global.set("timing",timing)`....

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [30 January 2022 17:23 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/56 "2022-01-30T17:23:27Z")

</div>

`let timing = global.get("timing")` does not give you a copy, it gives you a reference (pointer) to the object. If you want a copy you must clone it.

**[Edit]** The reason you still have to do global.set is so that node-red knows you have changed it and knows to flush it out to disc when appropriate (if it is in file storage). If you don't do the set it _may_ not get flushed.

---

<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:** [31 March 2022 17:23 UTC](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357/57 "2022-03-31T17:23:44Z")

</div>

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

[Previous page](https://discourse.nodered.org/t/error-in-a-function-in-node-re-2-2-not-present-in-previous-versoins/57357.md?page=2)
