array.push(element) vs. array = [...array, element]
Array.push adds an element to the end of the existing array while the spread syntax creates an entirely new array. For example, the following code will throw an error because we are trying to redefine a const:
const array = ["foo", "bar"];
array = [...array, "baz"]; // Uncaught TypeError: invalid assignment to const 'array'
Array.push adds to an existing array, so there is no need to redefine:
const array = ["foo", "bar"];
array.push("baz"); // No error; "baz" is successfully added to the end of the array.
Another difference is speed. array.push(element) is ~2,500 times faster than array = [...array, element];
As pointed out by @FelixKling, the spread syntax itself does not create a new array. You can also use the spread syntax in a function like this: myFunction(...myArray). This will use the array elements as arguments. So in other words, ...myArray will not create a new array, but [...myArray] will. Just a small detail worth noting.
Why your loop keeps referencing the same array in memory
The Spread syntax returns the correct solution, while the .push() method keeps on pushing onto the same array. I don't understand why it keeps referencing the same array in memory.
Objects in JavaScript (JavaScript arrays are objects) are reference types—not value types. Therefore, using the spread syntax, you create a new array (result), but still supply the old array (arr) to your function. When you use Array.push, you modify the array that was supplied to your function. And since you modify the array that was supplied (instead of creating a local one), you will keep calling your function with new values in the array. When you use the spread syntax, you create a new array (so result doesn't reference the arr array), and when you call your function with the arr parameter, you still have the same values as when you first called the function.
@trincot wrote a neat break down of what is going on in your code.
Here is an experiment you can do in a JavaScript console:
const myArray = ["foo", "bar"];
function changeArray(arrayParameter) {
const arrayVariable = arrayParameter;
// We are still referencing the array that was supplied to our function, so
// although it looks like we tried to duplicate the array, arrayVariable.push,
// arrayParameter.push, and myArray.push will all modify the same array.
arrayVariable.push("baz");
}
changeArray(myArray);
console.log(myArray); // ["foo", "bar", "baz"]
result = [...result, e];creates a new array. It's not due to using spread specifically, it's simply becauseresult = [ ]assigns a new array toresult.memo[target]entry refers to one and the same array, meaning the memoized solution for eachtargetis exactly the same, which is obviously conceptually wrong.