0

I bumped into some odd problem in my node application. If i take contents of one variable and assign to another it somehow crates a link between them in the way that if i change content in second variable it is also affecting the first one that i took content from.

this is my server structure:

var body = {};

now lets populate body:

body[_session] = {
    content: { /* some data here */ },
    sockets: []
};

then at some point i do this:

body[new_session] = {
    content: body[_session].content,
    sockets: []
};

at that point, changes made to new_session content will be also made on original _session content.

i solved this problem by doing this:

body[new_session] = {
    content: JSON.parse(JSON.stringify(body[_session].content)),
    sockets: []
};

but it seem like costly operation and something that could be avoided i just dont know yet how, maybe someone have an idea, why its happening and how it can be solved without much effort.

2 Answers2

1

That just creates a reference, you'll need to properly copy the body[_session].content's properties over to a new object.

If you're using ES6 then try Object.assign:

content: Object.assign({}, body[_session].content)

As you can see here: https://jsperf.com/object-assign-vs-iife - it's 3.5 times faster that the stringify/parse method whilst being more readable. I've included Mevia's solution to show that it is faster but more verbose and difficult to add to an existing, well structured code base.

Otherwise give a solution from here a go: How do I correctly clone a JavaScript object?

Joe
  • 15,205
  • 8
  • 49
  • 56
  • its almost the same as author solution, it just copy paste, its not good solution – Mevia Aug 11 '17 at 10:17
  • @Mevia - it's the only solution there is. It's similar to the author's but it does it in a more readable way, making use of a function the OP might not know about. If you have a better solution then please post it. – Joe Aug 11 '17 at 10:19
  • read my answer, its not the only solution, i presented solution that doesnt require any copy paste, it only does scope switch, which is far more better in terms of performance – Mevia Aug 11 '17 at 10:21
  • @Mevia - your solution is impractical when writing an application. It's in no way obvious and will cause maintainability issues when other devs come to work on it. – Joe Aug 11 '17 at 10:23
  • well what kind of argument is that? read a little sir http://markdalgleish.com/2011/03/self-executing-anonymous-functions/ it's a common practice to change scope, this is what it was made for, because what is obvious is the fact that author has scope problems, he is operating in one single scope, and that can cause maintainability issues, its one of that issues which my answer solves – Mevia Aug 11 '17 at 10:27
  • I fully understand JS scope, I meant that when the problem you're facing is "I want to copy one object's property to another object" then the most simple, easy to integrate solution is not to wrap everything in an IIFE. – Joe Aug 11 '17 at 10:33
0

The best solution (in terms of performance) would be to just do execute the assign command in self-executing anonymous function like this:

(function(__content) {
    body[new_session] = {
        content: __content,
        sockets: []
    };
}(body[_session].content));

above mentioned function type will create its own scope so link will be severed.

Dont do any cloning of constructor or properties of object its the same as what you already been doing.

Mevia
  • 1,517
  • 1
  • 16
  • 51
  • this indeed helped and seems to be flexible regardless of what ES version is used, i like this one, thx –  Aug 11 '17 at 10:33