Course: Section

Get Started with Modern React: Intro, Setup, and ES6 Basics

Episode: Title

S01・V11: Copying and Merging

Date Created: July 17th, 2019
Last Updated: 27 days ago

Objectives
  1. We will be covering the array methods “slice()” and “concat()”, for copying arrays and merging arrays, respectively.
  2. We will talk about “shallow copying”, and what it means for arrays with elements which are primitive values, versus elements which are objects.
  3. We will use the “Object.assign()” method for copying and merging objects.
  4. We will introduce the new “spread syntax”, and how it can simplify copying and merging both arrays and objects.
Watch Video
Duration: 9m 50s

slice()

If you want to copy an array, you can use the slice() method.

The slice() method has been available since JavaScript ES3. It returns a shallow copy of a portion of an array, or the entire array, into a new array. It does not modify the original array.

For example, let’s start with a simple array of numbers:

// COPY
const arr = [1, 2, 3];

We will use the slice() method to make a copy.

// COPY
const arr = [1, 2, 3];

const dup = arr.slice();

As no arguments are supplied to the slice() method, it makes a copy of the entire original array.

We will now modify the copy, by pushing the number 4 onto the end of the array:

// COPY
const arr = [1, 2, 3];

const dup = arr.slice();
dup.push(4);

We will print the modified copy to the Console. And, we will also print the original array.

// COPY
const arr = [1, 2, 3];

const dup = arr.slice();
dup.push(4);

console.log("dup:", dup); // Prints `dup: [1, 2, 3, 4]`console.log("arr:", arr); // Prints `arr: [1, 2, 3]`

You can see in the Console that the modified copy is a new array, while the original array is unchanged. Note that slice() returns a shallow copy of the elements from the original array.

If an element in the array is a primitive value, such as a string, number, or boolean value, then slice() copies the value into the new array. Changes to the string, number, or boolean values in one array, do not affect the other array.

Shallow Copying

If an element in the array is an object of any type, then slice() copies the object reference, not the actual object, into the new array. Both the original and new copied arrays refer to the same object. If a referenced object changes, the changes are visible to both the copied and original arrays. That is why we refer to it as “shallow” copying.

concat()

If you want to merge two arrays, then you can use the concat() method.

The concat() method has been available since JavaScript ES3. It returns a shallow copy that contains copies of the same elements combined from the original arrays. This method does not change the existing arrays, but instead returns a new array.

For example, let’s start with two simple arrays of numbers:

// MERGE
const arr1 = [4, 5, 6];
const arr2 = [7, 8, 9];

We will use the concat() method, called on the first array, passing the second array as its argument.

// MERGE
const arr1 = [4, 5, 6];
const arr2 = [7, 8, 9];

const mrg = arr1.concat(arr2);

We will print the merged array, and the original arrays, to the Console.

// MERGE
const arr1 = [4, 5, 6];
const arr2 = [7, 8, 9];

const mrg = arr1.concat(arr2);

console.log("mrg:", mrg); // Prints `mrg: [4, 5, 6, 7, 8, 9]`console.log("arr1:", arr1); // Prints `arr1: [4, 5, 6]`console.log("arr2:", arr2); // Prints `arr2: [7, 8, 9]`

You can see in the Console that the merged array is a new array, while the original arrays are unchanged.

Spread Syntax

We will now introduce “spread syntax” for array copying.

The array literal spread syntax has been available since JavaScript ES6. You can make a shallow copy of an array using “spread syntax”, which has the same effect as using the slice() method.

You can create a new shallow copy of the original array arr. Specify the array literal square brackets, then inside, put three dots, followed by the original array name.

[...arr]

Think of it like using the three dots to spread the elements of the original array into a new array literal. You can see the copy of the original array in the Console.

// COPY
const arr = [1, 2, 3];

// const dup = arr.slice();// dup.push(4);const dup = [...arr];
console.log("dup:", dup); // Prints `dup: [1, 2, 3]`
console.log("arr:", arr); // Prints `arr: [1, 2, 3]`

Now, if we had wanted to add the number 4 to the end of the array, as we did previously, then all we need to do is add the number 4 after the spread out array, after a comma:

// COPY
const arr = [1, 2, 3];

// const dup = arr.slice();
// dup.push(4);
const dup = [...arr, 4];
console.log("dup:", dup); // Prints `dup: [1, 2, 3, 4]`console.log("arr:", arr); // Prints `arr: [1, 2, 3]`

View the effect in the Console.

Merge Arrays

Let’s use the spread syntax to merge arrays.

We will perform the merge with spread syntax. We first specify the array literal square brackets. Then, we spread the contents of the first array... Then, a comma... And then, we spread the contents of the second array.

// MERGE
const arr1 = [4, 5, 6];
const arr2 = [7, 8, 9];

// const mrg = arr1.concat(arr2);const mrg = [...arr1, ...arr2];
console.log("mrg:", mrg); // Prints `mrg: [4, 5, 6, 7, 8, 9]`
console.log("arr1:", arr1); // Prints `arr1: [4, 5, 6]`
console.log("arr2:", arr2); // Prints `arr2: [7, 8, 9]`

We can see the new merged array, and the unchanged original arrays.

Copy Objects

Now, let’s make a shallow copy of an object.

We will use the Object.assign() method to make a copy of an object. This method has been available since JavaScript ES6.

Let’s start with a simple object with two properties and values:

// COPY
const obj = {foo: 'bar', x: 42};

The Object.assign() method takes the target object as its first argument, and the source object as its second argument. As the first argument, specify an empty object {} as the target object to copy into, followed by our original source object obj as the second argument to copy from. Assign the result to a variable called dup.

// COPY
const obj = {foo: 'bar', x: 42};

const dup = Object.assign({}, obj);

Now, we can modify the copy dup, for example, by setting the key x to the value 43.

// COPY
const obj = {foo: 'bar', x: 42};

const dup = Object.assign({}, obj);
dup.x = 43;

Let’s print out the modified copy and original objects to the Console.

// COPY
const obj = {foo: 'bar', x: 42};

const dup = Object.assign({}, obj);
dup.x = 43;

console.log("dup:", dup); // Prints `dup: {foo: 'bar', x: 43}`
console.log("obj:", obj); // Prints `obj: {foo: 'bar', x: 42}`

You can see in the Console that the copied object dup is a new array with a modified value for its key x.

Merge Objects

We can also merge two objects into a new object with Object.assign().

We will create 2 simple objects to start with.

// MERGE
const obj1 = {color: 'red', size: 24};
const obj2 = {margin: 6, padding: 12};

Now, we will create the merged object mrg. Call the Object.assign() method, and as its first argument, we will specify the target object to be a new empty object {}. The method can take a variadic number of arguments after the first target object argument, all of which represent source objects. So, we will pass the first obj1 and second obj2 objects as the second and third arguments respectively.

// MERGE
const obj1 = {color: 'red', size: 24};
const obj2 = {margin: 6, padding: 12};

const mrg = Object.assign({}, obj1, obj2);

Now, we will print the new merged object, and the original objects, to the Console.

// MERGE
const obj1 = {color: 'red', size: 24};
const obj2 = {margin: 6, padding: 12};

const mrg = Object.assign({}, obj1, obj2);

console.log("mrg:", mrg); // Prints `mrg: {color: 'red', size: 24, margin: 6, padding: 12}`console.log("obj1:", obj1); // Prints `obj1: {color: 'red', size: 24}`console.log("obj2:", obj2); // Prints `obj2: {margin: 6, padding: 12}`

Spread Syntax on Objects

We will now show you that you can use spread syntax on object literals, instead of Object.assign(), to shallow copy and shallow merge objects.

Object literal spread syntax has been available since JavaScript ES7. We will create a new copy dup of the original object obj.

Write an object literal {}, and spread the contents of our original object into it { ...obj }:

// COPY
const obj = {foo: 'bar', x: 42};

// const dup = Object.assign({}, obj);
// dup.x = 43;
const dup = { ...obj };
console.log("dup:", dup); // Prints `dup: {foo: 'bar', x: 42}`
console.log("obj:", obj); // Prints `obj: {foo: 'bar', x: 42}`

This is all we need to do in order to create a new shallow copy of the original object.

Now, to add the modification to the key x, as we did before, add a comma after the spread out original object, and then add the key x, with a modified value of 43, giving us { ...obj, x: 43 }:

// COPY
const obj = {foo: 'bar', x: 42};

// const dup = Object.assign({}, obj);
// dup.x = 43;
const dup = { ...obj, x: 43 };
console.log("dup:", dup); // Prints `dup: {foo: 'bar', x: 43}`console.log("obj:", obj); // Prints `obj: {foo: 'bar', x: 42}`

That’s how simple it is using the object literal spread syntax. There has been no change to the output, so the object literal spread syntax is equivalent.

Finally, let’s use the spread syntax to merge objects.

Add the object literal curly braces, spread the first object, follow with a comma, then spread the second object { ...obj1, ...obj2 }:

// MERGE
const obj1 = {color: 'red', size: 24};
const obj2 = {margin: 6, padding: 12};

// const mrg = Object.assign({}, obj1, obj2);
const mrg = { ...obj1, ...obj2 };

Print out the merged object mrg, and the original objects obj1 and obj2, to Console.

// MERGE
const obj1 = {color: 'red', size: 24};
const obj2 = {margin: 6, padding: 12};

// const mrg = Object.assign({}, obj1, obj2);
const mrg = { ...obj1, ...obj2 };

console.log("mrg:", mrg); // Prints `mrg: {color: 'red', size: 24, margin: 6, padding: 12}`console.log("obj1:", obj1); // Prints `obj1: {color: 'red', size: 24}`console.log("obj2:", obj2); // Prints `obj2: {margin: 6, padding: 12}`

Everything works as before.

Summary

We covered the array methods slice() and concat(), for copying arrays and merging arrays, respectively. We talked about “shallow copying”, and what it means for arrays with elements which are primitive values, versus elements which are objects. We used the Object.assign() method for copying and merging objects. And, we introduced the new “spread syntax”, and talked about how it can simplify copying and merging both arrays and objects.

Next Up…

In the next video, we will talk about “destructuring assignment” in JavaScript ES6.