I have a problem manipulating an array in Javascript that I have not been able to solve or explain the behavior.
Initially I have 9 buttons inside a div numbered 1 to 9. Clicking on button 5 the button numbers around it should rotate clockwise.
To do this I add an event (I can't use jQuery) directly manipulating the DOM. I create an array and add the 8 buttons in the respective order, clone the array, remove the last element from the cloned array and add it to the beginning (so I simulate moving the elements clockwise), then I assign the value of the objects from the cloned array to the new array.
The inconvenience that occurs is that it is assigning the number 4 to all the values that surround the number 5. To verify this, in the code I added two codes that, first, show me the permuted cloned array and the values are the appropriate ones, but in the second for loop, when redisplaying the values of the permuted array they are exactly the same (the number 4) without altering the array.
That could be happening?
var button5 = document.getElementById("btn5");
button5.onclick = function() {
var arrButtons = [];
//Inicialmente el arreglo contendrá los objetos a
//los botones representados por 1,2,3,6,9,8,7,4
arrButtons.push(document.getElementById("btn1"));
arrButtons.push(document.getElementById("btn2"));
arrButtons.push(document.getElementById("btn3"));
arrButtons.push(document.getElementById("btn6"));
arrButtons.push(document.getElementById("btn9"));
arrButtons.push(document.getElementById("btn8"));
arrButtons.push(document.getElementById("btn7"));
arrButtons.push(document.getElementById("btn4"));
//Clono el arreglo inicial.
var newButtons = arrButtons.slice();
//Permutar en el sentido de las agujas del reloj.
newButtons.unshift(newButtons.pop());
//Muestra el arreglo permutado correctamente
//De 1,2,3,6,9,8,7,4 ahora es 4,1,2,3,6,9,8,7 en la primera iteración
for (var i = 0; i < arrButtons.length; i++) {
console.log(newButtons[i].innerHTML);
}
for (var i = 0; i < arrButtons.length; i++) {
//Pero ahora solo muestra 4 para cada valor de newButtons[i] en la primera iteración
console.log(newButtons[i].innerHTML)
arrButtons[i].innerHTML = newButtons[i].innerHTML;
}
}
#btns {
width: 75%
}
#btns .btn {
width: 30%;
height: 48px;
font-size: 24px;
}
<div id="btns">
<button id="btn1" class="btn">1</button>
<button id="btn2" class="btn">2</button>
<button id="btn3" class="btn">3</button>
<button id="btn4" class="btn">4</button>
<button id="btn5" class="btn">5</button>
<button id="btn6" class="btn">6</button>
<button id="btn7" class="btn">7</button>
<button id="btn8" class="btn">8</button>
<button id="btn9" class="btn">9</button>
</div>
The problem is the order of the last loop. When you read the value of an element, it has already been updated in the previous step and it does not have the value you think it has (the old one) but a different one (the new one, which is 4).
Let's see it step by step:
And so with all the elements of the array. This happens because although they are two different arrays, the elements are the same in both arrays (you could see it as references to the same element). So by modifying the innerHTML of an element in one array, you are changing the innerHTML of the same element in the other array (which is in another position)
A possible solution would be to loop through the array in reverse. This way you don't run into that problem (although you'd still have a problem with the first/last element, so you'd need to store it in a variable and assign it last, as you need an extra variable when you want to swap values between two variables).