I am trying to write a fairly simple Javascript function, and experiencing behavior I don't understand when I iterate the function.
I have distilled the problem down to the following situation. I want to write a function that will take as input an array consisting of arrays of arrays, e.g. A = [[[1]]]
. I don't know the standard terminology for this, so I am going to refer to the main array as "level 0", which has elements that are arrays of "level 1". I'll say the level 1 arrays consist of arrays of "level 2". The level 2 arrays consist of integers.
The function does the following, on input A
(a level 0 array):
L
;M
in A
M
;M
to L
L
.Here is my code:
function myFunc(A){
var L = [];
for(var a=0; a<A.length; a++){
var M = A[a].slice(0);
for(var i=0; i<M.length; i++){
for(var j=0; j<M[i].length; j++){
M[i][j]++;
}
}
for(var s=0; s<2; s++){
var N = M.slice(0);
L.push(N);
}
}
return(L);
}
Now I test it out:
var A = [[[1]]];
A = myFunc(A)
After this, I get A = [[[2]],[[2]]]
, which is what I expect. However, suppose I iterate it:
var A = [[[1]]];
A = myFunc(A);
A = myFunc(A);
Then I expect to obtain A = [[[3]],[[3]],[[3]],[[3]]]
, but instead I have A = [[[4]],[[4]],[[4]],[[4]]]
.
On the other hand if I run myFunc([[[2]],[[2]]])
, I do get the expected [[[3]],[[3]],[[3]],[[3]]]
.
I don't understand where this discrepancy is coming from.
In order to run a function multiple times after a fixed amount of time, we are using few functions. setInterval() Method: This method calls a function at specified intervals(in ms). This method will call continuously the function until clearInterval() is run, or the window is closed.
You can't, it is only possible once.
One of the most common ways to create a loop is by using the for statement to create a for loop. A for loop allows us to repeatedly run some code until an expression we specify returns false.
debugger; statement there, and open the JavaScript console. There will be an option in that debugger to see a stack trace. The stack trace will let you see exactly where a function was called from, so you can see if it is being called from two different points.
The problem is the line:
M[i][j]++;
Node keeps this as a reference to your A's slice, and you see it clearly when you do this :
x = [[[1]]];
myFunc(x);
myFunc(x);
console.log(x); // ---> [[[3]]]
For a shallow copy you'd have to use the JSON.parse(JSON.stringify())
trick, and proof that M is the problem; adding this line just after M = A[a].slice(0);
solves the issue.
M = JSON.parse(JSON.stringify(M))
Mozilla's documentation about Array.prototype.slice()
:
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.
Source
That is why, because when you do M[i][j]
, the array a level deeper is still referenced outside.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With