Copying Array or Object can be tremendously confusing if we don’t know that they are different from primitive typed values like string, boolean, or number.

Let’s start with them. I can guarantee that we can copy primitive typed values this way.

  var year = 2017;
  var thisYear = year;

If we change the value of year to something else, then nothing happens to thisYear. As expected.

  year = 2016;
  console.log(year); // 2016
  console.log(thisYear); // 2017

The same thing goes to boolean and string values.

  var name = 'Robert';
  var hisName = name;
  var right = true;
  var left = right;

  name = 'James';
  right = false;

  console.log(name); // James
  console.log(hisName); // Robert
  console.log(right); // false
  console.log(left); // true

Let’s say we have an array.

  var players = ['Wes', 'Sarah', 'Ryan', 'Poppy'];

We try to make a copy of array the same way we copy number, boolean, and string.

  var team = players;

You might think we can just do something like this, expecting that players will not be affected.

  team[0] = 'Pop';

However what happens when we update that array?

  console.log(players); // ['Pop', 'Sarah', 'Ryan', 'Poppy']
  console.log(team); // ['Pop', 'Sarah', 'Ryan', 'Poppy']
  console.log(`Both share the same memory.`);

Now here is the problem! We have edited the original array too! Why? It’s because that is an array reference, not an array copy. They both point to the same array! So, how do we fix this?

  • By using old fashioned [].slice.
  var team = players.slice();
  team[0] = "James";
  console.log(players); // ['Wes', 'Sarah', 'Ryan', 'Poppy']
  console.log(team); // ['James', 'Sarah', 'Ryan', 'Poppy']
  • By using [].concat.
  var team = [].concat(players);
  team[0] = "James";
  console.log(players); // ['Wes', 'Sarah', 'Ryan', 'Poppy']
  console.log(team); // ['James', 'Sarah', 'Ryan', 'Poppy']
  • By using the new ES6 spread.
  var team = [...players];
  team[0] = "James";
  console.log(players); // ['Wes', 'Sarah', 'Ryan', 'Poppy']
  console.log(team); // ['James', 'Sarah', 'Ryan', 'Poppy']

Object and Array act the same way when it comes to copying its own properties. Let’s say we have a person object.

  var person = {
    name: "Dudung",
    lastName: "Stevenson"
  };

This kind of statement is completely wrong.

  var newPerson = person;

How do we fix that?

  • Using Object.assign instead.
  var newPerson = Object.assign({}, person, {isHandsome: false});
  console.log(newPerson);
  // {
  //   name: "Dudung",
  //   lastName: "Stevenson",
  //   isHandsome: false
  // }

  console.log(person);
  // It doesn't change.
  // {
  //   name: "Dudung",
  //   lastName: "Stevenson"
  // }
  • We will hopefully soon see {...spread}. It’s next generation of EcmaScript. Every cool kid will be using this frantically. It’s the future!
  var newPerson = {...person};

Things to note that this is only 1 level deep, both for Array and Object. Lodash has a cloneDeep method, but you should think twice before using it.

  // You can't just copy this nested object entirely with
  // any of those built-in methods. Only 1 level deep.
  {
    name: "Dudung",
    lastName: "Maman",
    education: {
      highSchool: "Cool Highschool",
      higherEducation: {
        bachelorDegree: "Stanford University",
        graduateDegree: "Harvard University"
      }
    }
  }

Well, I borrow too many words from Wes Bos. I owe him a beer. That’s it for today.