0

I'm wondering if array destructuring syntax that uses a rest element (be it an object or array) creates a new array in memory that is then used by that nested rest element's destructuring assignment? In other words, I'm wondering if syntax like:

let [a, b, ...[c, d]] = [1, 2, 3, 4];`

results in a new array being created after a and b are initialized for the ...[c , d] destructuring to then use?

I ask as MDN on their page about Destructuring Assignment in their section on "Using a binding pattern as the rest property" states:

The rest property of array destructuring assignment can be another array or object binding pattern. The inner destructuring destructures from the array created after collecting the rest elements, so you cannot access any properties present on the original iterable in this way.

This is in regards to such an example as I gave above. The last sentence states "from the array created after collecting the rest elements", which seems to indicate an entirely new array is thus being created for that destructuring?

My main curiosity in regards to this is about performance. Creating a new array (or iterable) seems slow, and so I'm wondering if this is implemented or specified another way? I have read the specification (linked under "Specification" on the above MDN page), but still have this question. I have also done a performance test using JSBench.me which seems to state that using the destructuring syntax as opposed to not (for instance, my above example as opposed to just

let [a, b, c, d] = [1, 2, 3, 4];

) is over 90% slower.

mishar
  • 89
  • 6
  • Back up a moment: what use-case would ever require the first example you show? – Mike 'Pomax' Kamermans Aug 19 '23 at 00:13
  • @Mike 'Pomax' Kamermans The first use case is just for illustration against an example that can achieve the same thing without the rest syntax. My question is in general though, when a rest element is used that is not simply an identifier, but itself an array or object, for whether a new array or object is created in that process. Basically if that syntax has performance hinderances to be mindful of. – mishar Aug 19 '23 at 00:29
  • 1
    Are you asking if the `...[c , d]` creates a new array (like where the array is created because there's an array in the source)? – Dave Newton Aug 19 '23 at 01:32
  • @Dave Newton yes that's what I'm asking: if the `...[c, d]` involves the creation of a new array from which `c` and `d` are then assigned? – mishar Aug 19 '23 at 03:31
  • @Dave Newton for instance, if instead of the `...[c, d]`, I did `...{'0': c, '1': d, length}`, then the example would instead be `let [a, b, ...{'0': c, '1': d, length}] = [1, 2, 3, 4];`, which would assign 1 to `a`, 2 to `b`, 3 to `c`, 4 to `d`, and 2 to `length`. Notice that `c` and `d` were treated as corresponding to indices `0` and `1`, respectively, and not `2` and `3`; and `length` to an array of length `2`, which has it appear that another array was created that this rest destructuring then used to assign `c`, `d`, and `length`. If that's the case it seems it's a performance hit? – mishar Aug 19 '23 at 03:44
  • I guess along what @Bergi answered below, I found in the ECMA specification on binding a rest element that's a binding pattern [here](https://tc39.es/ecma262/multipage/syntax-directed-operations.html#prod-QEcf_4fA) that a new array is indeed created, at least per the spec. – mishar Aug 19 '23 at 03:56

1 Answers1

1

Yes, rest syntax in destructuring is specified to create an array. If you are immediately destructuring it again, it is not observable by your code, so an engine could in theory optimise away the intermediate allocation without changing the behaviour of the code. However, such an unusual pattern is unlikely to be optimised for, it would not occur in good idiomatic code.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375