Weird array behavior in JavaScript

I’m trying to write a tool for visualizing the bubble sort algorithm.

The array arr holding all the values, that is to be sorted, is a global variable. The user clicks the "Fill" button btnFill to fill the array with unsorted, random numbers using the fillArray function. The function returns an array of objects: {val: x, col: "y"} where x is the value and col is a color class used for CSS.

When the array is filled, if the user clicks the "sort" button btnSort, the bubbleSort function is invoked where I guess my problem is:

This function saves a copy of the array arr on every iteration of the inner loop. This is an idea that I had since I was having a lot of issues using setInterval to animate – I could just save snapshots of the array during every stage of the sorting, and then pass it to the draw function so that there wouldn’t be any JavaScript weirdness combining loops and intervals.

The function finishes running and is expected (by me at least) to return an array filled with copies of the arr array from every loop iteration.

The actual behavior which I have tried to understand for hours is that the snapShot array is filled with arrays of a sorted arr. All elements are the same – sorted arrays. Doesn’t make sense to me since when debugging it comes out as sorted in console.log when it enters the sorting loop for the first time.

I appreciate any help greatly, thank you!

–EDIT–
I’m aware that the snapShot array gets sent as an array of arrays and will not be drawn to the screen but the problem is somewhere before that. That part was changed for debugging reasons

const btnFill = document.querySelector("#btnFill");
const btnSort = document.querySelector("#btnSort");
const container = document.querySelector(".container");

let arr = [];

btnFill.addEventListener("click", function () {
  arr = fillArray();
  draw(arr);
});

btnSort.addEventListener("click", function () {
  let sorted = bubbleSort();
  draw(sorted);
});

function bubbleSort() {
  let snapShots = [];
  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = 0; j < arr.length - 1 - i; j++) {
      if (arr[j].val > arr[j + 1].val) {
        let tmp = arr[j].val;
        arr[j].val = arr[j + 1].val;
        arr[j + 1].val = tmp;
        snapShots.push([...arr]);
      }
    }
  }
  return snapShots;
}

function fillArray() {
  const tmp = [];
  const len = 50;
  for (let i = 0; i < len; i++) {
    tmp[i] = { val: Math.floor(Math.random() * 100 + 1), col: "red" };
  }
  return tmp;
}

function draw(array) {
  container.innerHTML = "";
  for (let i = 0; i < array.length; i++) {
    const tmp = document.createElement("div");
    tmp.style.height = array[i].val + "%";
    tmp.classList.add("bar", array[i].col);
    container.appendChild(tmp);
  }
}

26 thoughts on “Weird array behavior in JavaScript”

Leave a Comment