ES6: Use the Spread Operator to Evaluate Arrays In-Place

I’m having some difficulty in understanding the use of the spread operator in the lesson where it’s introduced.

I’ve played around with it, and understand how it’s used in the example, however, I don’t understand the application in the exercise.

The new array arr2 doesn’t return a spread array: it’s an array which is identical to arr1. Whereas:

const newArray = [1, 2, 3];
console.log([...newArray]); //returns 1 2 3, not [1, 2, 3]

For example, if I initialise an array, then use the spread operator to assign a new array with the old array’s values, I can’t use the Math.max(...arr) on the new array; I still have to use the spread operator:

const arr = [1,2,3,4];

const arr2 = [...arr];

console.log(Math.max(arr2)); //returns 'NaN'
console.log(Math.max(...arr2)); //returns 4

If you needed to do exactly what is asked in the exercise, why would you do it this way as opposed to: let arr1 = arr2; or similar?

Sorry if this is convoluted: if it’s just a way to get us used to the syntax, all good. But I want to make sure that I’m not missing something.

Link to Lesson

Hello and welcome to the forum!

It’s important to note that in Javascript (like many other languages), variables only hold a single value. Consider the following code

const a = 10;

I have stored the single value 10 to a. I can copy this value to another variable.

// Initialize
const a = 10;
const b = a;

// View
console.log("a: " + a);
console.log("b: " + b);

This single value rule has implications when we are working with arrays. The single value in the variable is the location in memory where the array is stored.

// Initialize
const a = [1, 2, 3];
const b = a;

// View
console.log("a: " + a);
console.log("b: " + b);

Let’s modify a and see what happens to b.

// Initialize
const a = [1, 2, 3];
const b = a;

// Modify
a[1] = 42;

// View
console.log("a: " + a);
console.log("b: " + b);

The variables a and b point at the same location in memory, so they both see the same changes in the single array that was created.

This is where the spread operator comes in. The way we copied a into b is called a shallow copy. The spread operator lets us do a deep copy for arrays. (Note that for nested arrays or objects other techniques are required to make a deep copy.)

// Initialize
const a = [1, 2, 3];
const b = [...a];

// Modify
a[1] = 42;

// View
console.log("a: " + a);
console.log("b: " + b);

Now we have created a brand new array when we initialized b and stored this new array in a different location in memory. Changes in a are no longer seen by b.

The spread operator converts the contents of a into a comma separated list of values. We said, in words, "make a new array b using the contents of a".

This is where we come to your question about max(). Looking at the documentation, the max() function requires a comma separated list of values. The spread operator converts an array into a comma separated list of values, so it’s exactly what we need!

I hope this helped, but please let me know if I can clarify anything.

1 Like

Welcome Mary.

The new array arr2 doesn’t return a spread array: it’s an array which is identical to arr1 . Whereas:

const newArray = [1, 2, 3];
console.log([…newArray]); //returns 1 2 3, not [1, 2, 3]
It’s more accurate to say “references” rather than “returns”. I don’t understand your example - I can’t duplicated it. It may be something about how your console works. It also is what I would expect from console.log(...newArray); so perhaps it a typo.

Here is some values that I get:

const arr = [1,2,3,4];
console.log(arr);
// [1, 2, 3, 4]

console.log(...arr);
// 1 2 3 4

console.log([...arr]);
// [1, 2, 3, 4]

const arr2 = [...arr];
console.log(arr2);
// [1, 2, 3, 4]

console.log(Math.max(arr2)); 
// NaN

console.log(Math.max(...arr2));
// 4

console.log(Math.max(arr2[0], arr2[1], arr2[2], arr2[3]));
// 4

The last two are basically the same thing. The spread operator is taking those values in the array and spreading them out one by one. If your friend asked you to hand her a dozen eggs you could hand her a carton (an array, all bundled up). But if you used the spread operator, you would pass her the eggs one by one.

let arr1 = arr2;

That is valid JS but it is not doing what you think it is doing. Realize that those two variables do not hold arrays of data, they hold memory addresses (references) that point to a location in memory that holds the array data. This would copy the reference so you would have two variables pointing to the same location in memory. If you and your brother have the same address, that doesn’t mean that there are two houses.

Yes, it’s a bit weird and it commonly confuses people at first. It is the distinction between primitive data types (that behave like you’re expecting) and reference types (objects, functions, arrays, etc. … OK, technically in JS these are all just types of objects).

So, const arr2 = [...arr]; is a way to get a completely different array. You spreading out all those values: ...arr. You are wrapping them in a new array: [...arr]. And then then you are storing them into a new variable arr2. This will create two independent variables referencing two independent places in memory that just happen to (for now) hold the same numbers. What you suggested would be two variables pointing to one place in memory so changing one would also change the other.

Yes, this is weird, but keep at it and you’ll get it.

3 Likes

This is brilliant - thanks very much for taking the time to go through it all, much appreciated!

1 Like

Thanks for taking the time to work up those examples: they really helped my understanding!

1 Like