Assigning objects in Javascript: shallow or deep copy? [duplicate] - javascript

This question already has answers here:
JavaScript by reference vs. by value [duplicate]
(4 answers)
Closed 7 years ago.
I want to know if javascript does shallow or deep copy when copying objects.
const a = ['value1', 'value2'];
const b = ['value3', 'value4'];
const new_ab = [a, b];
new_ab are going to have new allocated values or a reference? If it is a deep copy, how can I make it to be swallow? Thanks.

As alluded in the comments, JavaScript operates entirely on references, the only exception being that primitive values are kept on the stack and a program does not therefore require a reference to access them. In your example all variable declarations create new values - each an instance of Array - however what is returned from declaring an array is a reference, not the array itself. For example, [1, 2] is an array of values (integers), but [a, b] is an array of references.
So... nothing is copied. We can demonstrate this by placing an object as an element of an array and inspecting that a previously assigned property is still accessible through the new 'parent' array.
(And to answer your question in the comments, yes, your example is more performant than if you (or JavaScript) were to copy values.)
'use strict';
const arrayOne = [];
arrayOne.someProperty = "This string is a property of `arrayOne`, " +
"accessed via the reference to it in `arrayTwo`."
const arrayTwo = [arrayOne];
span.innerHTML = arrayTwo[0].someProperty;
<span id="span"></span>

Related

Push the value of the array inside the same array. How deep can it go? Why doesn't the browser crash? [duplicate]

This question already has answers here:
Example of a circular reference in Javascript?
(8 answers)
Closed 3 years ago.
I wanted to know what happens if I push the value of an array inside the same array. I did it and there were no errors nor any problems. It just returned an array which has the same array inside that and so on...
I understand that array is passed through references but the pointer to the array still must take some memory.
So how deep does it go? And how do browsers handle this if they need to do it at all?
let arr = [1, 2, 3];
arr.push(arr);
Arrays are objects in JS, and objects are passed by references.
If you create an object, and set a property to a reference to that object, it will be infinite.
Your browser won't crash since the object stored only once, and every level loads the same object, so this won't occupy too much space.
The following equality will be true:
arr[3] === (arr[3])[3]
So arr[3][3] will be interpreted like:
Load arr (arr)[3][3]
Load arr[3] => Load arr (arr[3])[3]
Load arr[3] => Load arr (arr[3])
Output: arr (arr)

What should we do when we need to clone an object deeply [duplicate]

This question already has answers here:
What is the most efficient way to deep clone an object in JavaScript?
(67 answers)
How to Deep clone in javascript
(25 answers)
Closed 5 years ago.
According with what was sayed on another question:
The spread operator is like Object.assign and does not deeply clone an
object. The reason the JSON thing worked is because you created a
whole new object which would pass the strict equality check, however
all your components would update needlessly because nothing will pass
a strict equality check now.
Object.assign({}, ...prevState, ...newState) would create a new
top-level object, but it would not create a new object for any objects
nested in prevState or newState. However, you would have to carefully
update nested objects so as to avoid needless re-renders. This can get
tricky for deeply nested objects and arrays.
My question is.... what must we do when we need to return a new version of an object that have properties tha contains arrays? For example:
const foo = {
myArray: [1, 2, 3],
name: 'Hello world'
};
const clonedObj = { ...foo }
This will create a new object with a copy of name and it's content, a copy of myArray key BUT not with a copy of [1, 2, 3].
JSON.parse + JSON.stringify does the trick but don't look like a clean way.
What alternative do I have?
Thank you
const clonedObj = Object.assign({}, foo);
Object.assign

Splice doesn't copy array of objects [duplicate]

This question already has answers here:
How do you clone an array of objects in JavaScript?
(40 answers)
using splice(0) to duplicate arrays
(3 answers)
Closed 6 years ago.
In this plunk I have an example of an array of objects a that I copy with slice() to b. I alter one of the objects in a but it changes also b. Isn't slice supposed to copy the array, including its contents? I need a and b to have different pointers.
Javascript
var a = [{x1:1, x2:2}, {x1:3, x2:4}];
var b = a.slice();
a[1].x1 = 5;
console.log(b[1]);
this prints:
x1: 5
x2: 4
From MDN:
For object references (and not the actual object), slice copies object
references into the new array. Both the original and new array refer
to the same object. If a referenced object changes, the changes are
visible to both the new and original arrays.
For strings, numbers and
booleans (not String, Number and Boolean objects), slice copies the
values into the new array. Changes to the string, number or boolean in
one array does not affect the other array.
Performing a deep copy on objects in the array is difficult, but this answer suggests a way to do it, as long as your array only contains JSON-serializable content:
var clonedArray = JSON.parse(JSON.stringify(originalArray));
You can try to do Deep copy with jQuery:
var b = $.extend(true,{},a);
This does a proper deep copy of all your variables.

Javascript - array connect to another [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
When I assign a variable to another variable does it not link them together?
(1 answer)
Closed 9 years ago.
I have really weird situation:
when I do that code:
var origin_array = [1,2,3];
var m = origin_array;
m.pop();
alert(origin_array);
origin_array value will be 1,2
eventhough I didn't changed it
but if I make that code:
var x = 5;
var y = x;
y--;
alert(x);
x still be 5, it won't be connected to "x" as you can see from the 1st example.
So my question is how do I make the "m" array unique, which not change the origin array?
You need to explicitly make a (shallow) copy or clone of origin_array:
var m = origin_array.slice(0);
This is not needed for primitive values, such as strings and numbers.
It's important to understand that although the above will prevent the issue you were experiencing, the same may happen again deeper down if you're dealing with more complex structures, and in some cases a "deep clone" is necessary.
Arrays are assigned by reference. That means that when you do this:
var origin_array = [1,2,3];
var m = origin_array;
m just points to the exact same array as origin_array. There is only one array and both origin_array and m point to it. If you modify it via either variable, they will both see the modification because you're modifying the one array that they both point to.
In javascript, both objects and arrays are assigned by reference like this. Assigning them does NOT make a copy. If you want an assignment to generate a copy, you have to explicitly make a copy. For an array, that is easy as you can just do:
var origin_array = [1,2,3];
var m = origin_array.slice(0); // makes a shallow copy
m.pop();
console.log(origin_array); // [1,2,3] because origin_array was not changed

copying an array of objects in javascript [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Copying array by value in javascript
How to copy an array of objects to another array in Javascript?
var qwerty1 = arr;
var qwerty2 = arr;
Both qwerty1 and qwerty2 may look different but point to the same reference.
I read somewhere that "assigning a boolean or string to a variable makes a copy of that value, while assigning an array or an object to a variable makes a reference to the value." So my two arrays post different operations return the same objects.
Any light in this regard?
The idiomatic way to copy an array in Javascript is to use concat:
var qwerty1 = arr.concat();
var qwerty2 = arr.concat();

Categories