1
\$\begingroup\$

I recently learned about the difference between a copy and a deep copy. Some people where writing some rather lengthy functions to in order to create a deep copy.

Then I was just playing around and wondering if there is anything wrong with the following method:

var newDeepCopy = originalArray.concat();

Right, so... just concat the original array with... nothing? Am I missing anything?

\$\endgroup\$

closed as off-topic by Phrancis, forsvarir, Vogel612, alecxe, Mast Mar 13 '17 at 12:58

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ stackoverflow.com/a/41439847/2445295 \$\endgroup\$ – user93 Mar 13 '17 at 4:53
  • 2
    \$\begingroup\$ By "deep copy," do you mean this array contains objects? If it doesn't, it only contains strings and numbers, then sure, your way would work. But if it contains objects, then you are cloning a reference to the same object. With your code above, if you do something like originalArray[0].p1 = 'newvalue' then newDeepCopy[0].p1 will be set to the same thing. \$\endgroup\$ – mherzig Mar 13 '17 at 6:38
  • 1
    \$\begingroup\$ This is a hypothetical question, which is off-topic for Code Review. Especially if there's as little to see as here. Your question may already have been answered at Software Engineering, another site on Stack Exchange. Please take a look at the help center. \$\endgroup\$ – Mast Mar 13 '17 at 12:57
1
\$\begingroup\$

What you're doing there is copying the array, not its contents. I.e. it's a shallow copy.

As mherzig mentions in a comment, what you end up with is an extra array containing references to the same elements as the first one. As long as those elements are primitive/immutable values, you're fine. But not so with other objects.

Besides, the conventional way of copying an array is to use slice() or slice(0) - not concat() (although the result is the same).

Anyway, as an example:

var obj = { foo: "bar" };
var array1 = [1, 2, obj];

// shallow copy
var array2 = array1.concat();

// changing a primitive works as you might expect
array2[0] += 10;
console.log(array1); // => [1, 2, { foo: "bar" }]
console.log(array2); // => [11, 2, { foo: "bar" }]

// but the object hasn't been copied, merely referenced in two places,
// so changing it via one array means it's changed in the other as well
array2[2].foo = "Hello, world!";
console.log(array1); // => [1, 2, { foo: "Hello, world!" }]
console.log(array2); // => [11, 2, { foo: "Hello, world!" }]

Hence why people go to great lengths to make deep copies, where the entire contents is copied, so there are no shared references to the same things.

Basically, you want shallow copies if you're just going to be manipulating the array itself (e.g. calling push, pop, splice, sort etc.), and don't want side-effects. E.g. a function that takes an array as its argument is usually best served making a shallow copy, if it intends to mess around with that array.

You want deep copies if you truly want to copy everything, because you're going to be changing the contents, or because you want to avoid other code altering something you hold a reference to.

\$\endgroup\$
  • \$\begingroup\$ Thanks Flambino! You're entirely correct.. I didn't try changing the values of the nested objects and arrays, but I can see now how those were merely references, not copies. Thanks for answering my off-topic question. XD \$\endgroup\$ – TJBlackman Mar 13 '17 at 16:12
  • \$\begingroup\$ @TJBlackman Oh, right, it's kinda off-topic, I guess. I wasn't even looking at that :) Anyway, yeah, off-topic, but glad you found it useful nonetheless. \$\endgroup\$ – Flambino Mar 13 '17 at 17:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.