Javascript passing arrays to functions by value, leaving original array unaltered

前端 未结 9 1712
不思量自难忘°
不思量自难忘° 2020-11-28 11:01

I\'ve read many answers here relating to \'by value\' and \'by reference\' passing for sending arrays to javascript functions. I am however having a problem sending an array

相关标签:
9条回答
  • 2020-11-28 11:27

    A generic solution would be...

    // Use the JSON parse to clone the data.
    function cloneData(data) {
      // Convert the data into a string first
      var jsonString = JSON.stringify(data);
    
      //  Parse the string to create a new instance of the data
      return JSON.parse(jsonString);
    }
    
    // An array with data
    var original = [1, 2, 3, 4];
    
    function mutate(data) {
      // This function changes a value in the array
      data[2] = 4;
    }
    
    // Mutate clone
    mutate(cloneData(original));
    
    // Mutate original
    mutate(original);
    

    This works for objects as well as arrays.

    Very effective when you need deep cloning or you don't know what the type is.

    Deep cloning example...

    var arrayWithObjects = [ { id: 1 }, { id: 2 }, { id: 3 } ];
    
    function mutate(data) {
      // In this case a property of an object is changed!
      data[1].id = 4;
    }
    
    // Mutates a (DEEP) cloned version of the array
    mutate(cloneData(arrayWithObjects));
    
    console.log(arrayWithObjects[1].id) // ==> 2
    

    Warnings

    • Using the JSON parser to clone is not the most performant option!

    • It doesn't clone functions only JSON supported data types

    • Cannot clone circular references

    0 讨论(0)
  • 2020-11-28 11:33

    by default in javascript except objects and arrays, everything is copy-by-value but if you want to use copy-by-value for arrays: use [yourArray].slice(0) and for objects use Object.assign(target, ...sources)

    0 讨论(0)
  • 2020-11-28 11:35

    What about destructuring assignment (ES6+, check compatibility)? Nice and clean solution.

    function myFunction(someArray) {
    
      for(let i = 0; i < someArray.length; i++)
      {
        someArray[i].reverse();
      }
      
      return someArray;
    }
    
    let myArray = [["A","B","C"],["D","E","F"],["G","H","I"]];
    
    // Using destructuring assignment.
    // NOTE: We can't just use `[...myArray]` because nested arrays will still be copied by reference.
    let anotherArray = myFunction([...myArray.map(nested => [...nested])]);
    
    console.log({original: myArray, copy: anotherArray});

    0 讨论(0)
  • 2020-11-28 11:38

    Inside your function there's this:

    funcArray = new Array();
    funcArray = someArray;
    

    This won't actually copy someArray but instead reference it, which is why the original array is modified.

    You can use Array.slice() to create a so-called shallow copy of the array.

    var funcArray = someArray.slice(0);
    

    The original array will be unaltered, but each of its elements would still reference their corresponding entries in the original array. For "deep cloning" you need to do this recursively; the most efficient way is discussed in the following question:

    What is the most efficient way to deep clone an object in JavaScript?

    Btw, I've added var before funcArray. Doing so makes it local to the function instead of being a global variable.

    0 讨论(0)
  • 2020-11-28 11:40

    A variable pointing to an array is a reference to it. When you pass an array, you're copying this reference.

    You can make a shallow copy with slice(). If you want a full depth copy, then recurse in sub objects, keeping in mind the caveats when copying some objects.

    0 讨论(0)
  • 2020-11-28 11:51

    Make a copy of the array that you can use.

    A simple way to do this is by using var clone = original.slice(0);

    0 讨论(0)
提交回复
热议问题