JavaScript Array concat with Non-Array Arguments
In JavaScript, Array.prototype.concat() merges two or
more arrays into a single new array, but it also accepts non-array
values as arguments. While arrays are automatically unpacked (flattened
by one level) into the result, non-array arguments—such as primitive
values, plain objects, and standard array-like objects—are appended
directly as individual elements. This guide explains how the
concat method processes different non-array data types and
how you can override this default behavior using
Symbol.isConcatSpreadable.
Primitive Values
When you pass primitive values (such as numbers, strings, booleans,
null, undefined, symbols, or BigInts) to
concat(), JavaScript treats each primitive as an individual
element and appends it to the newly created array.
const baseArray = [1, 2];
const result = baseArray.concat(3, 'hello', true, null, undefined);
console.log(result);
// Output: [1, 2, 3, 'hello', true, null, undefined]Objects and Functions
Plain objects, functions, dates, regular expressions, and other reference types are not flattened. The reference to the object is simply added as a single element in the resulting array.
const baseArray = ['a', 'b'];
const userObject = { id: 1, name: 'Alice' };
const result = baseArray.concat(userObject);
console.log(result);
// Output: ['a', 'b', { id: 1, name: 'Alice' }]Because reference types are copied by reference (shallow copy), mutating the original object after the concatenation will reflect in the new array.
Array-like Objects
By default, array-like objects (such as arguments,
NodeList, or custom objects with numeric keys and a
length property) are treated as plain objects rather than
arrays. Consequently, concat() inserts the entire
array-like object as one element instead of spreading its indexed
values.
const baseArray = [1, 2];
const arrayLike = {
0: 'a',
1: 'b',
length: 2
};
const result = baseArray.concat(arrayLike);
console.log(result);
// Output: [1, 2, { 0: 'a', 1: 'b', length: 2 }]Controlling
Behavior with Symbol.isConcatSpreadable
JavaScript uses the well-known symbol
Symbol.isConcatSpreadable to determine whether an argument
should be flattened by concat():
- Arrays: Spreadable by default
(
true). - Non-arrays / Objects: Not spreadable by default
(
falseorundefined).
You can explicitly set [Symbol.isConcatSpreadable]: true
on an array-like object to force concat() to flatten its
indexed elements into the new array.
const baseArray = [1, 2];
const spreadableArrayLike = {
[Symbol.isConcatSpreadable]: true,
0: 'a',
1: 'b',
length: 2
};
const result = baseArray.concat(spreadableArrayLike);
console.log(result);
// Output: [1, 2, 'a', 'b']Conversely, setting [Symbol.isConcatSpreadable]: false
on an array causes concat() to treat that array as a single
element without unpacking it.
Summary
Array.prototype.concat() distinguishes between values
based on their spreadability:
- Primitives and standard objects are appended as single items.
- Array-like objects are not unpacked unless explicitly configured.
Symbol.isConcatSpreadablecontrols whether any object or array is flattened during the concatenation process.