HOWTO · JavaScript

How to Compare Two Arrays in JavaScript

This tutorial provides a comprehensive guide on how to compare two arrays in JavaScript. Explore various methods like JSON.stringify, Array.prototype.every, and custom sorting functions. Learn through practical code examples and detailed explanations, ensuring you grasp array comparison techniques effectively. Enhance your JavaScript skills today with this informative article.

On this page

JavaScript’s === operator compares arrays by identity, so two separately created arrays with the same contents are not equal by that check. To compare their contents, choose a rule for order and for element values. For primitive values in the same order, compare lengths and then compare each corresponding element. Use JSON.stringify() only when its serialization rules fit your data; when order does not matter, compare sorted copies. These basic approaches compare nested arrays and objects by reference, not by structure.

What does it mean for two arrays to be equal?

First decide what “equal” means for the task. An ordered comparison requires the same length and a match at every index. An order-independent comparison treats the arrays as collections, but must still account for duplicate values: [1, 1, 2] is not equivalent to [1, 2, 2] just because both contain the same distinct values.

Also decide whether element equality is shallow or structural. Strict equality works well for matching primitive values such as numbers and strings. For objects and nested arrays, strict equality checks whether both positions refer to the same object; it does not compare their properties or nested contents.

Compare arrays in order with a loop or Array.prototype.every()

A standalone function avoids changing the built-in Array.prototype. This version checks the length first, then compares corresponding values with strict equality. It is an ordered, shallow comparison.

Run this example:

function arraysEqual(left, right) {
  if (left.length !== right.length) return false;
  return left.every((value, index) => value === right[index]);
}

const first = ["red", "green", "blue"];
const second = ["red", "green", "blue"];
console.log(arraysEqual(first, second));
true

The function also rejects a changed value and a different length. These additional calls are unexecuted examples:

function arraysEqual(left, right) {
  if (left.length !== right.length) return false;
  return left.every((value, index) => value === right[index]);
}

console.log(arraysEqual(["red", "green"], ["red", "blue"]));
console.log(arraysEqual(["red", "green"], ["red", "green", "blue"]));

The first call returns false because the second elements differ; the second returns false because the lengths differ.

A for loop can express the same rule when you want to customize the comparison at each index: reject different lengths, return false at the first mismatch, and return true after every position matches. Array.prototype.every() is more concise and stops as soon as its callback returns false. It skips unassigned slots in sparse arrays, so for sparse input its result may differ from a loop that reads each index; use dense arrays or define a hole-handling rule if that distinction matters.

Compare arrays with JSON.stringify()

For arrays containing JSON-compatible values, comparing their serialized forms is concise: JSON.stringify(left) === JSON.stringify(right). It is order-sensitive, so [1, 2] and [2, 1] produce different comparisons. Serialization also has specific rules: unsupported values such as undefined in an array serialize as null, and object properties with undefined values are omitted. Distinct objects with equivalent serializable properties can serialize alike, but this is not a general deep-equality definition. Property order and custom serialization behavior can also affect the result. Choose this method only when those rules match the data contract; do not use it as a universal equality check or assume it is faster for larger arrays.

Compare arrays regardless of order

When order is irrelevant and elements are primitives, sort shallow copies and compare the resulting positions. Calling sort() directly on the inputs would mutate them, so copy first with slice(). The default sort compares string representations; provide a comparator when the values need a different ordering, such as numeric values. Sorting takes additional work, and mixed types need an explicit ordering policy. The length and element checks still preserve duplicate counts.

For primitive strings, sort copies and compare each resulting value with strict equality. This complete, unexecuted example logs the comparison result and both original arrays:

function arraysHaveSameValues(left, right) {
  if (left.length !== right.length) return false;
  const sortedLeft = left.slice().sort();
  const sortedRight = right.slice().sort();
  return sortedLeft.every((value, index) => value === sortedRight[index]);
}

const left = ["pear", "apple", "pear"];
const right = ["pear", "pear", "apple"];
console.log(arraysHaveSameValues(left, right));
console.log(left);
console.log(right);

For these arrays, the comparison rule returns true, and sorting the copies leaves both inputs in their original order. Sorting both copies and comparing every position also preserves duplicate counts: arrays with different numbers of a value do not match. The default sort and strict equality rule here are intended for strings; mixed values need a comparator and equality rule designed for their types. For objects, define a key that represents the intended equality or use a matching strategy designed for those values; default sorting does not establish object equality.

Handle nested arrays and objects

The ordered comparison and sorting examples use strict equality for each element. Thus two separately created values such as [{ id: 1 }] compare unequal at that position even though their visible properties match. The same applies to nested arrays. If structural equality is required, use a recursive comparison that defines behavior for every supported type, or a purpose-built deep-equality library appropriate to the application. Specify how it should treat dates, maps, sets, prototypes, cycles, and special numeric values before relying on it; different deep-equality tools can implement different contracts.

For data that is known to be JSON-compatible, serialization can sometimes provide a compact structural comparison, with the limitations described above. Otherwise, make the equality contract explicit and test the cases that matter to the application. The practical choice is the simplest method that matches the required ordering and value semantics: every() or a loop for ordered primitive values, serialization for suitably constrained JSON data, and a deliberate matching or deep-equality strategy for other requirements.