Merge array-like objects by Array.prototype.concat()

smlka

Andrey Smolko

Posted on June 27, 2024

Merge array-like objects by Array.prototype.concat()

Let's dive into the Array.prototype.concat() method in JavaScript. This handy method helps you merge arrays, creating a new array with elements from the arrays you provide. Here's a quick example:

const arr0= [], arr1 = [1,2], arr2 = [3,4];
const resultArray = arr0.concat(arr1, arr2);
// [1,2,3,4]
Enter fullscreen mode Exit fullscreen mode

Now, let's switch things up and try to concatenate some array-like objects:

const arr0 = [];
const arr1 = {0:1, 1:2, length:2};
const arr2 = {0:3, 1:4, length:2};
const resultArray = arr0.concat(arr1, arr2);
// [{...}, {...}]
Enter fullscreen mode Exit fullscreen mode

When you use array-like objects, Array.prototype.concat() doesn't flatten them like it does with arrays. Instead, it treats each array-like object as a single element.

So, is there a way to force Array.prototype.concat() to flatten array-like objects too? Sounds like a challenge for the JavaScript geeks! Let's figure it out together.

Array.prototype.concat() description from ECMAScript specification:

Image description

Let's pay attention to step5.a. There is a boolean variable spreadable which defines how Array.prototype.concat() treats its arguments. If spreadable is false (step 5.c) then an argument is added in resulting array as it is without been flatten. But if spreadable is true (step 5.b) then the argument can be flattened!

Function IsConcatSpreadable defines value of spreadable variable:

  1. If O is not an Object, return false.
  2. Let spreadable be ? Get(O, @@isConcatSpreadable).
  3. If spreadable is not undefined, return ToBoolean(spreadable).
  4. Return ? IsArray(O).

In step 2 - @@isConcatSpreadable is just a specification name of build-in Symbol Symbol.isConcatSpreadable.
The function IsConcatSpreadable returns true in 2 two cases: either the object is an array or it has the property with the name Symbol.isConcatSpreadable and the property value is not falsy.

This looks exactly like what we need! Let's add Symbol.isConcatSpreadable in array-liked objects we tried to concatenate:

const arr0 = [];
const arr1 = {0:1, 1:2, length:2, [Symbol.isConcatSpreadable]:true};
const arr2 = {0:3, 1:4, length:2, [Symbol.isConcatSpreadable]:true};
const resultArray = arr0.concat(arr1, arr2);
// [1,2,3,4] 
Enter fullscreen mode Exit fullscreen mode

Solved! Now Array.prototype.concat() flattens our array-like objects just like it does with regular arrays.

P.S. Symbol.isConcatSpreadable is used exclusively by the Array.prototype.concat() method. No other build-in methods uses it.

💖 💪 🙅 🚩
smlka
Andrey Smolko

Posted on June 27, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related