How to Merge Two Arrays in JavaScript Full Guide

Learn every way to merge arrays in JavaScript. Covers the spread operator, concat, push, unshift, reduce, merging without duplicates, merging arrays of objects, performance comparisons, and common mistakes.

JavaScriptbeginner
13 min read

Merging arrays is one of the most common operations in JavaScript. Whether you are combining API responses, concatenating search results, or building a unified dataset from multiple sources, you need a reliable way to join two or more arrays into one. JavaScript provides several approaches, each with different behavior around immutability, performance, and readability.

This guide covers every method for merging arrays, from the modern spread operator to classic techniques, plus patterns for merging without duplicates and merging arrays of objects.

The spread operator is the most readable and widely used approach. It creates a new array without mutating the originals.

javascriptjavascript
const fruits = ["apple", "banana", "cherry"];
const vegetables = ["carrot", "broccoli", "spinach"];
 
const combined = [...fruits, ...vegetables];
 
console.log(combined);
// ["apple", "banana", "cherry", "carrot", "broccoli", "spinach"]
 
console.log(fruits);     // ["apple", "banana", "cherry"] -- unchanged
console.log(vegetables); // ["carrot", "broccoli", "spinach"] -- unchanged

Merging Multiple Arrays

javascriptjavascript
const team1 = ["Alice", "Bob"];
const team2 = ["Charlie", "Diana"];
const team3 = ["Eve", "Frank"];
 
const allTeams = [...team1, ...team2, ...team3];
console.log(allTeams);
// ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank"]

Adding Elements While Merging

javascriptjavascript
const existing = [1, 2, 3];
const additional = [7, 8, 9];
 
const withMiddle = [...existing, 4, 5, 6, ...additional];
console.log(withMiddle);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Method 2: Array.concat()

The concat() method returns a new array by joining the original with one or more arrays or values. It predates the spread operator and is fully supported in every environment.

javascriptjavascript
const a = [1, 2, 3];
const b = [4, 5, 6];
 
const merged = a.concat(b);
console.log(merged); // [1, 2, 3, 4, 5, 6]
 
// Chaining multiple
const c = [7, 8, 9];
const all = a.concat(b, c);
console.log(all); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
 
// Concat with individual values
const withValues = a.concat(4, 5, [6, 7]);
console.log(withValues); // [1, 2, 3, 4, 5, 6, 7]

Method 3: Array.push() with Spread (Mutating)

If you want to add elements to an existing array instead of creating a new one, use push with the spread operator:

javascriptjavascript
const primary = ["HTML", "CSS", "JavaScript"];
const secondary = ["React", "Node.js", "TypeScript"];
 
primary.push(...secondary);
 
console.log(primary);
// ["HTML", "CSS", "JavaScript", "React", "Node.js", "TypeScript"]
// Note: primary is mutated

push() vs. Spread into New Array

javascriptjavascript
// Immutable: creates a new array
const immutable = [...primary, ...secondary];
 
// Mutable: modifies 'primary' in place
primary.push(...secondary);

Method 4: Array.unshift() with Spread

To prepend one array before another, use unshift with spread:

javascriptjavascript
const tasks = ["code", "test", "deploy"];
const priorityTasks = ["plan", "design"];
 
tasks.unshift(...priorityTasks);
 
console.log(tasks);
// ["plan", "design", "code", "test", "deploy"]

Method 5: reduce() for Complex Merging

Use reduce when you need to merge with transformation or filtering logic:

javascriptjavascript
const arrays = [[1, 2], [3, 4], [5, 6], [7, 8]];
 
const flat = arrays.reduce((result, current) => [...result, ...current], []);
console.log(flat); // [1, 2, 3, 4, 5, 6, 7, 8]
 
// With filtering during merge
const numbers = [[1, -2, 3], [-4, 5, -6], [7, 8, -9]];
 
const positiveOnly = numbers.reduce((result, current) => {
  return [...result, ...current.filter((n) => n > 0)];
}, []);
 
console.log(positiveOnly); // [1, 3, 5, 7, 8]

Merging Without Duplicates

Using Set

The simplest way to merge arrays and remove duplicates is combining spread with Set:

javascriptjavascript
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];
 
const unique = [...new Set([...arr1, ...arr2])];
console.log(unique); // [1, 2, 3, 4, 5, 6, 7]

Using filter() for Deduplication

javascriptjavascript
const arr1 = ["JavaScript", "Python", "Go"];
const arr2 = ["Python", "Rust", "Go", "Java"];
 
const merged = [...arr1, ...arr2.filter((item) => !arr1.includes(item))];
console.log(merged); // ["JavaScript", "Python", "Go", "Rust", "Java"]

Deduplicating Arrays of Objects by Key

javascriptjavascript
const list1 = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" }
];
 
const list2 = [
  { id: 2, name: "Bob" },
  { id: 3, name: "Charlie" }
];
 
const mergedUnique = [...list1, ...list2].reduce((acc, item) => {
  if (!acc.some((existing) => existing.id === item.id)) {
    acc.push(item);
  }
  return acc;
}, []);
 
console.log(mergedUnique);
// [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }, { id: 3, name: "Charlie" }]

Merging Arrays of Objects

Combining API Response Pages

javascriptjavascript
const page1 = [
  { id: 1, title: "Introduction to JS", views: 1200 },
  { id: 2, title: "Variables Guide", views: 950 }
];
 
const page2 = [
  { id: 3, title: "Functions Tutorial", views: 1800 },
  { id: 4, title: "Arrays Explained", views: 2100 }
];
 
const allArticles = [...page1, ...page2];
console.log(allArticles.length); // 4
 
// Sort merged results by views
const sorted = allArticles.sort((a, b) => b.views - a.views);
console.log(sorted[0].title); // "Arrays Explained"

Merge and Group by Category

javascriptjavascript
const electronics = [
  { name: "Laptop", price: 999, category: "electronics" },
  { name: "Phone", price: 699, category: "electronics" }
];
 
const clothing = [
  { name: "Shirt", price: 29, category: "clothing" },
  { name: "Jacket", price: 89, category: "clothing" }
];
 
const inventory = [...electronics, ...clothing];
 
// Group by category using reduce
const grouped = inventory.reduce((groups, item) => {
  const key = item.category;
  groups[key] = groups[key] || [];
  groups[key].push(item);
  return groups;
}, {});
 
console.log(Object.keys(grouped)); // ["electronics", "clothing"]

Comparison Table

MethodMutates OriginalCreates New ArrayPerformance (Large Arrays)Readability
[...a, ...b]NoYesGoodExcellent
a.concat(b)NoYesGoodGood
a.push(...b)YesNoBest (no copy)Good
a.unshift(...b)YesNoSlower (shifts indices)Fair
reduce mergeNoYesDepends on logicComplex

Common Mistakes

Accidentally Nesting Instead of Merging

javascriptjavascript
const a = [1, 2, 3];
const b = [4, 5, 6];
 
// Bug: creates a nested array
const nested = [a, b];
console.log(nested); // [[1, 2, 3], [4, 5, 6]]
 
// Fix: spread both arrays
const flat = [...a, ...b];
console.log(flat); // [1, 2, 3, 4, 5, 6]

push() Without Spread

javascriptjavascript
const items = [1, 2, 3];
const moreItems = [4, 5, 6];
 
// Bug: pushes the array itself as a single element
items.push(moreItems);
console.log(items); // [1, 2, 3, [4, 5, 6]]
 
// Fix: spread into push
const items2 = [1, 2, 3];
items2.push(...moreItems);
console.log(items2); // [1, 2, 3, 4, 5, 6]

Shallow Copy with Object Arrays

javascriptjavascript
const original = [{ name: "Alice" }, { name: "Bob" }];
const copy = [...original];
 
copy[0].name = "Charlie";
console.log(original[0].name); // "Charlie" -- original mutated!
 
// Fix: deep copy when objects must be independent
const safeCopy = structuredClone(original);

Best Practices

  1. Use spread for immutable merges. [...a, ...b] is the default choice for combining arrays without side effects.
  2. Use push with spread for performance. When mutation is acceptable and you are adding to an existing array, arr.push(...newItems) avoids creating a copy.
  3. Deduplicate with Set. [...new Set([...a, ...b])] is the most concise approach for primitive values.
  4. Use reduce for complex merges. When you need filtering, transformation, or grouping during the merge, reduce provides full control.
  5. Be aware of shallow copies. Spreading arrays of objects shares nested references. Use structuredClone() when full independence is required.
Rune AI

Rune AI

Key Insights

  • Spread operator is the modern default: [...a, ...b] creates a new merged array without mutating originals.
  • concat() is the classic alternative: it behaves identically to spread for merging but uses method chaining syntax.
  • push with spread mutates efficiently: arr.push(...items) is fastest when immutability is not required.
  • Set deduplication is one line: [...new Set([...a, ...b])] removes duplicate primitives automatically.
  • Nested objects require deep awareness: spread produces shallow copies, so merged arrays of objects share inner references.
RunePowered by Rune AI

Frequently Asked Questions

What is the fastest way to merge two arrays in JavaScript?

For mutating merges, `push(...arr)` is fastest because it avoids creating a new array. For immutable merges, both spread (`[...a, ...b]`) and `concat()` perform similarly on arrays up to 100,000 elements. Beyond that, `push` with spread into an existing array wins on performance. For most application code, readability matters more than microsecond differences.

How do I merge arrays without duplicates?

Combine spread with `Set` for primitive values: `[...new Set([...arr1, ...arr2])]`. For arrays of objects, use `reduce` with a lookup by unique key (like `id`). The Set approach is fastest for primitives, while the reduce approach gives you control over which property defines uniqueness.

Does concat mutate the original array?

No. `concat()` always returns a brand new array and leaves both originals unchanged. This makes it safe for functional programming patterns where immutability is required. If you specifically want to mutate the original, use `push(...items)` instead.

Can I merge more than two arrays at once?

Yes. Both spread and concat support any number of arrays: `[...a, ...b, ...c, ...d]` or `a.concat(b, c, d)`. There is no practical limit on the number of arrays you can merge in a single expression, but very long spreads may impact readability.

How do I merge arrays of objects and keep the latest version?

Use a Map keyed by the unique identifier. Iterate through both arrays in order; later entries overwrite earlier ones. Then spread the Map values back into an array: `[...new Map([...arr1, ...arr2].map(item => [item.id, item])).values()]`. This keeps the last occurrence of each unique key.

Conclusion

JavaScript offers multiple ways to merge arrays, and the right choice depends on whether you need immutability, deduplication, or raw performance. The spread operator is the default for most situations because it is immutable, readable, and works with any number of arrays. Use push with spread when mutation is acceptable and performance matters, Set for automatic deduplication of primitives, and reduce for complex merge-with-transform logic. Understanding these options lets you handle any array combination scenario cleanly.