admin管理员组

文章数量:1400749

I would like to work with an array passed to a function while leaving the original array untouched. Here is a simple example of the problem.

function whyDoesArrChange(arr) {
   var newArr = arr;
   newArr.push(4);

   return arr;
 }
 
 console.log(whyDoesArrChange([1,2,3]));
// OUT: [1,2,3,4]

I would like only newArr to be changed, but the arr (from the arguments) returns the pushed value as well (returns [1,2,3,4]). How can I avoid this?

I would like to work with an array passed to a function while leaving the original array untouched. Here is a simple example of the problem.

function whyDoesArrChange(arr) {
   var newArr = arr;
   newArr.push(4);

   return arr;
 }
 
 console.log(whyDoesArrChange([1,2,3]));
// OUT: [1,2,3,4]

I would like only newArr to be changed, but the arr (from the arguments) returns the pushed value as well (returns [1,2,3,4]). How can I avoid this?

Share Improve this question edited Nov 25, 2020 at 2:09 brasofilo 26.1k15 gold badges94 silver badges186 bronze badges asked May 1, 2017 at 22:14 user1486510user1486510 1391 silver badge10 bronze badges 1
  • The answer is going to depend upon whether the elements in the array need to be untouched as well. As Marcos Casagrande has already suggested, you can use slice to generate a subset of the original array. Doing so, will copy any objects in that array by reference. – Jon Trauntvein Commented May 1, 2017 at 22:23
Add a ment  | 

4 Answers 4

Reset to default 7

When passing an array to a function, the value of that array is a reference, you have to clone it to break the reference.

There are multiple ways to achieve this:

1 - Using .slice();

var newArr = arr.slice();

2 - Using .concat

var newArr = arr.concat([]);

3 - Using JSON.parse & JSON.stringify

var newArr = JSON.parse(JSON.stringify(arr));

You can check more ways and see how they perform in this jsperf I found.

While Marcos' answer is correct, no doubt. There are more pure Array functions that can be used (A pure function is a function that doesn't alter data outside of its' scope).

Usually, if you'd like to do multiple actions on the array, I would go with Marcos' answer and then do those changes as usual. But when that's not the case, the following information may be useful:

  1. Adding: arr.concat([1]);
  2. Subarray (i to j): arr.slice(i, j + 1);
  3. Removing (i to j): arr.slice(0, i).concat(arr.slice(j + 1));

Also, filter and map are pure function that will not alter the array.

In JavaScript, when you use (=) to assign a value from a variable to another one, you're just passing the entire variable, so each time one or another changes, the other will change too.

According to your question, the best way that works for me is using the native .slice() JavaScript method to the arrays object. For your code:

function whyDoesArrChange(arr) {
    var newArr = arr.slice();
    newArr.push(4);
    return arr;
}

Because reference types (arrays and objects) can get modified inside functions when passed as arguments, while primitive types (numbers, strings, booleans etc.) don't.

You can make a shallow copy the array with .slice() and work on that array, or return a new array with the .concat method.

function whyDoesArrChange(arr) {
   return arr.concat(4);
 }

本文标签: