Delete copied array item without deleting the item from its source - VueJS

I would like to clone a list of numbers and be able to manipulate that cloned list without making change to the source, but in the following situation when I delete the item from the cloned array it deletes the source.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
  <div id="app">
    <ul>
      <h3>Lista Origem</h3>
      <li v-for="item in listaOriginal">
        {{item}}
      </li>
    </ul>

    <ul>
      <h3>Lista Clone</h3>
      <li v-for="item in listaClone">
        {{item}}
      </li>
    </ul>

    <button @click="clonaLista">Clonar Lista</button>
    <button @click="removerItem">Remover item do Clone</button>
  </div>

  <script>
    const vue = new Vue({
      el: "#app",
      data: {
        listaOriginal: [1, 2, 3],
        listaClone: []
      },

      methods: {
        clonaLista() {
          this.listaClone = this.listaOriginal
        },

        removerItem() {
          this.listaClone.pop()
        }
      }
    })
  </script>
</body>

</html>
Author: Rodolfo Santos, 2019-11-12

3 answers

Rodolfo this is because the Array is a reference type. When you say that listaClone = listaOriginal both variables point to the same array. To solve use a spread to clone effectively:

this.listaClone = [...this.listaOriginal];
 1
Author: Marcelo Vismari, 2019-11-12 18:55:25

There are several ways to copy an array, but you need to know if you want a shallow copy (shallow copy) or a deep copy (deep copy) 1.

If you are just working with primitive types like Number, String or Boolean will not make a difference you use a shallow or deep copy. From the moment your array contains other arrays or objects, you'll be working with references if you just copy those references you will be making a shallow copy, but if you make a copy of the object to the new array, you will be making a deep copy.

let array = [1, 2, 3, 4];
let copia = array;  // cópia da referência

copia.push(5);

// Como `array` e `copia` referenciam o mesmo
// objeto em memória, alterações feitas em 
// ambos inferem no mesmo objeto
console.log(array);
// [1, 2, 3, 4, 5]

Some methods to create shallow Copy

  1. Array.slice (#docs & compatibility )

    David Walsh posted in this article a way to make a shallow copy using the method Array.slice. The big advantage of this method is its compatibility with old browsers.

    let array = [1, 2, 3];
    let copia = array.slice(0);
    
    copia.push(4);
    
    console.log(array);  // [1, 2, 3]
    console.log(copia);  // [1, 2, 3, 4]
    
  2. Spread operator ( # docs & compatibility )

    let array = [1, 2, 3];
    let copia = [...array];
    
  3. For loop

    let array = [1, 2, 3];
    let copia = [];
    
    for (let i=0, l=array.length ; i<l ; i++) {
        copia.push(array[i]);
    }
    
  4. Array.map (#docs & compatibility )

    let array = [1, 2, 3];
    let copia = array.map(x => x);
    

Methods for creating deep copy

  1. JSON.stringify e JSON.parse (compatibility )

    You can use JSON.stringify e JSON.parse to create deep copies of objects.

    let array = [[1], [2], [3]];
    let copia = JSON.parse(JSON.stringify(array));
    
    copia[0].push(1.5);
    
    console.log(array); // [[1], [2], [3]]
    console.log(copia); // [[1, 1.5], [2], [3]]
    
  2. _.cloneDeep (#docs )

    If you are using the lodash library, you can use the function _.cloneDeep.

    let array = [[1], [2], [3]];
    let copia = _.cloneDeep(array);
    
    copia[0].push(1.5);
    
    console.log(array); // [[1], [2], [3]]
    console.log(copia); // [[1, 1.5], [2], [3]]
    

This article mentions some other methods you can use to create shallow copies.

 1
Author: fernandosavio, 2019-11-12 19:43:13

You can get a copy of the array by doing this:

let array = [1, 2, 3];
let copy  = array.slice()

The way you did was not copying the array, but referencing the same. :)

 0
Author: Hufman, 2019-11-12 22:01:51