Day 14: JavaScript Challenge
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 ofEcmaScript
. 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.