最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Difference between Array.push() and Spread syntax - Stack Overflow

programmeradmin4浏览0评论

Algo Problem Statement: Find the smallest array that adds up to the target sum.

Code Issue: I do not understand the difference in results when:

  • using the arr.push() method

vs.

  • using the Spread syntax

Please reference the ment line below.

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.

Many thanks in advance!

let howSum = (target, arr, memo = {}) => {
    if (target in memo) return memo[target];
    if (target === 0) return [];
    if (target < 0) return null;

    let smallest = null;

    for (let e of arr) {
        if (howSum(target - e, arr, memo) !== null) {
            let result = howSum(target - e, arr, memo);
            // result.push(e);
            result = [...result, e];

            if (smallest === null || result.length < smallest.length) {
                smallest = result;
            }
        }
    }

    memo[target] = smallest;
    return smallest;
};

console.log(howSum(10, [1, 2, 5])); // [5, 5]

Algo Problem Statement: Find the smallest array that adds up to the target sum.

Code Issue: I do not understand the difference in results when:

  • using the arr.push() method

vs.

  • using the Spread syntax

Please reference the ment line below.

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.

Many thanks in advance!

let howSum = (target, arr, memo = {}) => {
    if (target in memo) return memo[target];
    if (target === 0) return [];
    if (target < 0) return null;

    let smallest = null;

    for (let e of arr) {
        if (howSum(target - e, arr, memo) !== null) {
            let result = howSum(target - e, arr, memo);
            // result.push(e);
            result = [...result, e];

            if (smallest === null || result.length < smallest.length) {
                smallest = result;
            }
        }
    }

    memo[target] = smallest;
    return smallest;
};

console.log(howSum(10, [1, 2, 5])); // [5, 5]
Share Improve this question asked Dec 17, 2020 at 23:34 PmcorreaPmcorrea 751 gold badge1 silver badge6 bronze badges 4
  • 5 result = [...result, e]; creates a new array. It's not due to using spread specifically, it's simply because result = [ ] assigns a new array to result. – Felix Kling Commented Dec 17, 2020 at 23:38
  • 4 Well, the answer to "I don't understand why it keeps referencing the same array in memory" is that it's by design. If used appropriately, there is a lot of utility in mutating objects instead of creating new ones. – Nick Commented Dec 17, 2020 at 23:43
  • @FelixKling, thank you. Can you elaborate a little more? The endgame is to update the array with the addition of a new element. Don't both methods acplish updating the older array? I can either update the same array, or create a new array with the updated value. – Pmcorrea Commented Dec 17, 2020 at 23:51
  • 1 I guess if you don't create a new array then every memo[target] entry refers to one and the same array, meaning the memoized solution for each target is exactly the same, which is obviously conceptually wrong. – Felix Kling Commented Dec 18, 2020 at 0:13
Add a ment  | 

2 Answers 2

Reset to default 11

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"]

the .push() method keeps on pushing onto the same array. I don't understand why it keeps referencing the same array in memory.

If we take the variant of your code where you don't use the spread syntax, but push, then realise that:

  • push mutates the array, it doesn't create a new one
  • The only place where your code creates a new array is at return []

So, look at what happens after that return []:

  • result.push(e); will alter that array into [e].
  • The first time smallest is null, so smallest bees a reference to that single array.
  • Another reference is made to that single array at memo[target]
  • This reference is returned to the caller, which assigns it to result.
  • A new value is pushed to that single array, which now has two elements. And here it es:
  • As the above mentioned memo[target] references the same array as result, you have actually mutated that memo[target]: memo[target].length will now be 2.

This is undesired. Once you have assigned an array to memo it should never mutate. This is why at some point in your code you should make a new array.

发布评论

评论列表(0)

  1. 暂无评论