3

I am working on a small personal project and I ran over something that I don't understand and I am hoping if someone can explain it to me. One of the methods in my module is SaveSet() which takes an array and adds it to a different array as an element so it become two dimensional array here is the code for the SaveSet():

function SaveSet() {
    anim.push(set)
}  

When I run this code I expect it to take whatever is in the set array and adds it to the anim array as an element like this.

Set = [1,2,3,4]
SaveSet()
Set = [3,4,5,6]
SaveSet()

and I should end up with something like this:

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

However, my SaveSet() is modifying the existing one and adding a new one so I end up with something like this

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

I found a work around it by changing my SaveSet() to this:

function SaveSet() {
    let temp = JSON.stringify(set)
    anim.push(JSON.parse(temp));
}  

However, I still can't understand why anim.push is modifying the existing one as well. This is the full code incase if anyone wants to look at it. As I said this a personal quick project so the quality of the code and design are really low. https://codepen.io/anon/pen/oJZeJy?editors=1111

9
  • The sample code in your question does not reflect accurately the actual code int the codepen. Commented Dec 21, 2018 at 14:21
  • 6
    Set is a built in collection in JS (like a mathematical set). Don't use it as a variable name. Also don't see why you are using a function at all since you're referencing a global. Commented Dec 21, 2018 at 14:25
  • Something like function saveSet( ary, addition ) { ary.push( addition); return ary; } will go a long way with avoiding such issues in code logic, since it requires you to explicitly send it the array to change and the array to add. You'll have to read a bit about object references and such if you want a thorough explanation. Commented Dec 21, 2018 at 14:26
  • @JaredSmith I wrote this code really fast I am not sure why :D. it's true it's a bad practice but I don't think changing it will solve the issue. Commented Dec 21, 2018 at 14:33
  • As @Shilly said with current practices I wouldn't run into such an issue but I am still interested in why this is happening. I would think array.push will add a new element and keep the old ones untouched but that is not the case here. Commented Dec 21, 2018 at 14:33

3 Answers 3

6

You are always using the same array for all of your data.

What is happening is that you're initializing a set = [] once globally in your code.

Then each time you save a set, you are adding this array into the anim array but you never update what the variable set is pointing to.

So you just keep adding the same set array over and over:

var set = [];
var anim = [];

function addToSet() {
  set.push(String(Math.random()).slice(2,3));
  console.log(set);
}

function saveSet() {
  anim.push(set); // <--- you are always pushing the same array
  console.log(anim);
}
<button id="add" onclick="addToSet()">Add to set</button>
<button id="save" onclick="saveSet()">Save set</button>

Each time you save a set you should create a new set:

function saveSet() {
  anim.push(set);
  set = []; // <---- reset the set to a new array
}
Sign up to request clarification or add additional context in comments.

6 Comments

I do want to keep the same array and modify it the boxes in the html will check red onclick and add an element to the array and remove them from the array when I right click on them so set = []; will not work for me as I want to keep the array. When I check a specific number of boxes and add that to the array it works but when I add or remove some boxes and hit save it will change the first and add new one. I did some tests in chromes console and this behavior didn't happen!
Last set = [] will not help as in he is re assign set = [3,4,5,6] , which is basically new array.
@Mohammed understand that anim.push(set); does not make a copy of the set array. If you want separate arrays in the anim list, you have no choice but to either re-initialize set between each .push() or else push a copy you make explicitly.
The notion of "new" array isn't based on the data it contains but on the memory location. The set variable always points to the same location in memory for you and you always push and slice values from/to this location.
@Pointy so anim.push(set) does makes an array with a pointer to set which will change as set is changing????? Is this what is going on? Because I always thought that array.push create a spot in memory that holds whatever is in it kind of like a variable! These are some new news to me!
|
0

With using .push method, you are pushing a pointer into your array. If you change your code to

function SaveSet() {
    anim.push([...set])
}  

it'll create a new array, spread current elements of set and push them to anim.

Your set array is probably changed because of a bug in another part of the code. It's not related to here

Comments

0

You should do the following :

var anim = []
function SaveSet(set){
  anim.push(set);
}
var set = [1,2,3,4];
SaveSet(set);
set = [3,4,5,6];
SaveSet(set);

1 Comment

Why should OP do the following?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.