Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array destructuring and spread operator

It's not 100% clear to me how this piece of code works:

var a = [1, 2, 3];

[x, y, ...a ] = [0, ...a, 4];

// OUTPUT:  [0, 1, 2, 3, 4]

I'm deconstructing the array a using the ... operator.

I am expecting that in second line a bunch of assignments will take place.

The x will be assigned to 0, y will be assigned to ...a (which passes the elements in the array a as individual values).

It's not clear to me, though, how the ...a get assigned to 4. In fact, JS throws an exception when doing:

...a = 4;
// Uncaught SyntaxError: Rest parameter may not have a default initializer

Why does this code output the modified array with the end 4, instead of throwing an exception? How does this work exactly?

like image 390
leonardofed Avatar asked Oct 19 '25 03:10

leonardofed


2 Answers

It is executed like following

var a = [1, 2, 3];
[x, y, ...a ] = [0, ...a, 4];
[x, y, ...a ] = [0, 1, 2, 3, 4];

which means first value in RHS array is assigned to x, second value in RHS array is assigned to y and the remaining values are assigned to a.

Hence, value of x is 0, y is 1 and a is [2, 3, 4]

like image 182
Nikhil Aggarwal Avatar answered Oct 21 '25 17:10

Nikhil Aggarwal


It's not clear to me, though, how the ...a get assigned to 4.

It's not.

Lets split things up a little:

On the right hand side of the assignment you are using an array literal with a spread element. The value of a is "flattened" into the new array.

Thus, [0, ...a, 4] is is equivalent to [0].concat(a, [4]). The result is a new array.

var a = [1, 2, 3];

console.log('spread element', [0, ...a, 4]);
console.log('concat', [0].concat(a, [4]));

On the left hand side you are using array destructuring with a rest element. [x, y, ...a ] means

  • assign the first value of the iterable to x
  • assign the second value of the iterable to y
  • assign the remaining values of the iterable as an array to a

These two are equivalent:

var a = [1,2,3,4];
var [x, y, ...z] = a;
console.log('destructuring', x, y, z);

var x = a[0];
var y = a[1];
var z = a.slice(2);
console.log('manual + slice', x, y, z);

Of course combining these two is perfectly fine. In an assignment, the left hand side doesn't care what how the right hand side is computed and vice versa.

What's confusing about your example is that you are using a again in the destructuring assignment, but that's the same as overriding the value of a with a new value. However the end result is

  • [0, ...a, 4] results in [0,1,2,3,4] therefor
  • x has value 0
  • y has value 1
  • a has value [2,3,4]

In fact, JS throws an exception when doing: ...a = 4;

The error message you are getting is strange. It should really be just a syntax error.

... by itself doesn't mean anything. It's not an operator, it's a punctuator (like ; or ,) that has a different meaning depending on the context it is used (and allowed).

See also What is SpreadElement in ECMAScript documentation? Is it the same as Spread operator at MDN?

like image 39
Felix Kling Avatar answered Oct 21 '25 15:10

Felix Kling



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!