Merge array-like objects by Array.prototype.concat()
Andrey Smolko
Posted on June 27, 2024
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]
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);
// [{...}, {...}]
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:
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:
- If O is not an Object, return false.
- Let spreadable be ? Get(O, @@isConcatSpreadable).
- If spreadable is not undefined, return ToBoolean(spreadable).
- 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]
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.
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
November 29, 2024