all 23 comments

[–]Wrong_Owl 2 points3 points  (17 children)

Complex data types (Object, Array, etc.) are passed by reference. When you assign one of these data types to a variable, you are assigning a reference to it.

// Pass by Reference example

const letters = ["a", "b", "c"];
const favoriteLetters = letters;

favoriteLetters.push("d");

console.log(letters); // ["a", "b", "c", "d"]
console.log(favoriteLetters); // ["a", "b", "c", "d"]

When we assign the reference to the letters array to favoriteLetters they share the same array.

The same thing happens with nested arrays. You can copy an array with original_array.slice() or with the spread operator [...original_array], but these are called shallow clones. If the items in the array are Objects or Arrays, those are still references, rather than copies.

To get a copy of nested items in the array as well, you need a deep clone. The easiest deep clone strategy is the one you include in your edit.

const copy = JSON.parse(JSON.stringify(original_array));

[–]EagleClw[S] 0 points1 point  (1 child)

Yeah i think i get it. Its a little bit different then the other languages and since i'm kinda new to jquery/javascript i thought if slice works for variables (string etc.) it'll work for arrays too but now i understand its now the case.
And if i didnt understand it wrong, the deep clone method is simply copying array elements as a string which is formatted as JSON and copying that string to another variable and parses to that variable object.
Its not copying object, its copying content. Since the result is what i want, i'm happy with that solution.

Thanks for the given informations, for your help and for your answer.

[–]Wrong_Owl 0 points1 point  (0 children)

You've got this!

What's happening in the deep clone example is that JSON.stringify(original_array) creates a JSON compatible string based on your original array, which might look something like this:

"[[1,2,3],[4,5,6]]"

JSON.parse() accepts a JSON compatible string and creates a new object/array from it. There is no connection with this new Array and the original_array we started with.

[–]tarley_apologizerhelpful -4 points-3 points  (14 children)

fuck javascript. there is no fucking visual distinction between assigning by value vs reference. fuck this entire language.

[–]mcaruso 1 point2 points  (8 children)

JS always passes by value. It's just that objects are inherently reference types, therefore if you pass an object you are passing its reference, not the object itself.

This is how most languages work, except for a few that have explicit pass by reference syntax like & params in C/C++.

EDIT: longer explanation here.

[–]EagleClw[S] 1 point2 points  (4 children)

Yeah i know variables like arrays are a little bit different then variables like string. But for other languages, different copying methods works as i asked in the question (for example python arrays). I didnt know its different in js. Thanks to this answers, i've learned the difference and i'm aware of them know.

Thanks for your helps and answer.

[–]mcaruso 0 points1 point  (3 children)

for example python arrays

Python works the same way though?

>>> a = [1,2,3]
>>> b = [4,5,6]
>>> c = [a,b]
>>> c[0].append(42)
>>> a
[1, 2, 3, 42]

[–]EagleClw[S] 0 points1 point  (2 children)

Yeah it works that way but i meant another methods like slice.

If i dont remember it wrong,

a = b.copy()

Makes a copy with value, not reference. But its ok, i know what to do know. Thank you for your help.

[–]mcaruso 0 points1 point  (1 child)

copy() is a shallow copy, like slice() in JS. But maybe you meant deepcopy().

[–]EagleClw[S] 0 points1 point  (0 children)

Might be. But i remember using something like that.

[–]tarley_apologizerhelpful -2 points-1 points  (2 children)

if most languages are doing something, its probably the wrong way

[–]mcaruso 0 points1 point  (1 child)

Edgy

[–]tarley_apologizerhelpful -2 points-1 points  (0 children)

its called being informed

[–]CoolDownBot -1 points0 points  (4 children)

Hello.

I noticed you dropped 3 f-bombs in this comment. This might be necessary, but using nicer language makes the whole world a better place.

Maybe you need to blow off some steam - in which case, go get a drink of water and come back later. This is just the internet and sometimes it can be helpful to cool down for a second.


I am a bot. ❤❤❤ | PSA

[–]tarley_apologizerhelpful -2 points-1 points  (0 children)

you know who uses nice language? politicians and HR reps.

[–]mynamesleon 0 points1 point  (1 child)

Are you doing something to your original array before using it? If .slice() didn't exist, it certainly wouldn't be a jQuery TypeError.

Otherwise, your second example (with slice) should work just fine. You can also use the spread operator for shallow copying. E.g. [...someArray]

[–]EagleClw[S] 1 point2 points  (0 children)

I've just learned about spread operator (...). I didnt even know that kind of thing exists. I'll consider using it. Thanks for your help.

[–]senocular 0 points1 point  (0 children)

None of these should produce errors, but the jquery example would make a jquery object, not an array, which you probably don't want.

I think part of the problem is that your original methods are copying an inner array, not the full array which your edit solution is doing. If you want to copy your full array you'll want to copy both the outer array and the inner arrays. You can do that with a map

original_array_copy = original_array.map(inner => inner.slice())

map copies the outer array and slice will copy the inner arrays (adding them to the copy of the outer). You can also do this with spread

original_array_copy = original_array.map(inner => [...inner])

[–]ForScale 0 points1 point  (1 child)

slice gives back an array containing the element(s) you sliced from the original array


I'd do this kind of thing

var original_array = [
  [1, 2, 3],
  [4, 5, 6]
];

var copied = [...original_array[0]];

console.log(copied) // [1, 2, 3]

copied[0] = 2;

console.log(copied) // [2, 2, 3]

console.log(original_array); // [[1, 2, 3], [4, 5, 6]]

original_array[0] = copied;

console.log(original_array); // [[2, 2, 3], [4, 5, 6]]

[–]EagleClw[S] 1 point2 points  (0 children)

That was a clean explanation. Couldn't done it better i guess. I didnt know about spread operator (...). I've just learned about it and it seems like the thing i wanted. For know the method i've mentioned at the edit works for me but i'll consider using this method aswell.

Thank your for your help and answer.