Function with two outputs

Dear colleagues
I'm not new to node-red, but I'm no programming experts neither.
While working on a flow, I tried to figure out how to create more than one message in a function node. I did read the documentation about the function node. And I thought I understood. But a very small tests showed me, that I don't.
Here is the test. I would be grateful for an explanation, why I can't duplicate an incoming message, change payload and topic, and create two different outgoing messages.

[{"id":"87c6db9f.4b9aa8","type":"inject","z":"b46b7fa0.7b04d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"test1","payload":"1","payloadType":"num","x":320,"y":340,"wires":[["702af256.a9349c","e1e2c7bb.a1d0f8"]]},{"id":"702af256.a9349c","type":"function","z":"b46b7fa0.7b04d","name":"worsk as expected","func":"var msg1 = {};\nmsg1.topic = \"test2\";\nmsg1.payload = 2;\nreturn [msg, msg1];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":540,"y":340,"wires":[["615b50d6.65b8f"],["7ac6ed31.699dc4"]]},{"id":"615b50d6.65b8f","type":"debug","z":"b46b7fa0.7b04d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":320,"wires":[]},{"id":"7ac6ed31.699dc4","type":"debug","z":"b46b7fa0.7b04d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":360,"wires":[]},{"id":"e1e2c7bb.a1d0f8","type":"function","z":"b46b7fa0.7b04d","name":"works in mysterious ways","func":"var msg1 = msg;\nmsg1.topic = \"test2\";\nmsg1.payload = 2;\nreturn [msg, msg1];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":540,"y":420,"wires":[["db315194.668608"],["4b1a05c.59d27fc"]]},{"id":"db315194.668608","type":"debug","z":"b46b7fa0.7b04d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":400,"wires":[]},{"id":"4b1a05c.59d27fc","type":"debug","z":"b46b7fa0.7b04d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":790,"y":440,"wires":[]}]

This is a case in Javascript where its called 'assigment by reference'
when you do var msg1 = msg; and change the values, msg1 is simply a pointer in memory to msg and you modify this way the original message.
This i believe applies to object and arrays and you wll not see the same with premitive variables like numbers, strings

[EDIT] you can avoid it - pointing to the same memory and hence when you change the new msg in essence changing the original one too by using the spread operator ...

var msg1 = {...msg};

There a nice video by dcode that better explains and demonstrates this
Passing by reference vs. by value

The spread operator will not do a deep clone so this will only work if your object you are cloning is only one layer deep.
Node-red actually provides cloning functionality in the form of

var newMsg = RED.util.cloneMessage(msg))

which uses one of the available npm modules for cloning.
You can also use the hackish way which is:

var newMsg = JSON.parse(JSON.stringify(msg))

Johannes

Edit:
You can read more about it here


Dont know if the nodered functionality isnt also based on lodash which is mentioned in this article.

Watch out for that. It is very fragile. Really, you should always wrap the JSON functions in a try/catch

var newMsg = {}
try {
    newMsg = JSON.parse(JSON.stringify(msg))
catch {}

:+1:t2: Yes i m aware, thats why i called it hackish and linked the article.

Thanks, I'll go with the node-red way of cloning a message.
This by-reference stuff freaks me out, you never know what you have and some other process might change what you think you have. I'm too old for this.
(BTW: in my coding for my ESP based sensors (Arduino IDE) I very often make Strings (upper case) out of values, just to make sure that I have my own thing in my hand and not just a lousy pointer to a place in the memory.)
Thanks again, cloning is the way forward.

Well, the advantages of references vs copies is clear and mostly works in our favour. Node-RED based on constant copies of data being passed between nodes would be horrible. And mostly it "just works". Async programming can be a pain though for that odd occasion when something gets changed and flows through all the references at the "wrong time" in your nice linear logic :unamused: