# How to compare arrays in JavaScript

![array.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1662213596464/cqky2Kw9II.jpg align="left")

# array1 === array2 ?
To compare arrays in JavaScript, don't assume you can check whether the contents of two JavaScript arrays are the same with `===` or `==` (the [strict equality](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) or [equality](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) operators). You can't.
```
const array1 = [1, 2, 3];
const array2 = [1, 2, 3];

array1 === array2    // returns false
```
The code above is checking if the above two variables refer to the same array instance, and not whether their contents are the same. It would only return true for something like this:
```
const array1 = [1, 2, 3]
const array2 = array1;     // both variables point to the same array instance

array1 === array2  // now returns true
```
# Solutions
### JSON.stringify()
One way to solve the problem is to use [JSON.stringify()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), which converts a value to a JSON string.
 ```
const array1 = [1, 2, 3];
const array2 = [1, 2, 3];

JSON.stringify(array1) === JSON.stringify(array2)   // returns true
```
JSON.stringify even works with multiple levels of nesting:
```
const array1 = [1, 2, 3, {x: 5}, [1, {y: 7}, 3]];
const array2 = [1, 2, 3, {x: 5}, [1, {y: 7}, 3]];

JSON.stringify(array1) === JSON.stringify(array2);    // returns true
```

However, this method is not perfect. It is dependent on the JSON.stringify() method implementation not changing. There are also edge cases that produce strange behavior. Undefined is not a valid JSON value, so JSON.stringify() converts undefined to null, and this method could falsely return true in that case:
```
const array1 = [null, 2, 3];
const array2 = [undefined, 2, 3];


JSON.stringify(array1) === JSON.stringify(array2)
  // returns true, should be false

null === undefined     
  // returns false
```

### array.every()
Another method uses array.every(). It first checks if the arrays are the same length, and then checks that each value in the first equals the value in the second at the same index:
```
const isEqual = array1.length === array2.length 
&& array1.every((value, index) => value === array2[index])

console.log(isEqual);
```
However, the array.every() way won't work for arrays nested with additional arrays or objects, which would need to be checked recursively. 
### Recursive methods
This can be done with the isEqual method from the [Lodash](https://lodash.com/) library. According to [this gist](https://gist.github.com/jsjain/a2ba5d40f20e19f734a53c0aad937fbb), it is doing something under the hood like the following:
```
const array1 = [1, [1, [{a: 'b'}]], 3];
const array2 = [1, [1, [{a: 'b'}]], 3];

const isEqual = (first, second) => {
  if (first === second) {
    return true;
  }
  if ((first === undefined || second === undefined 
|| first === null || second === null) && (first || second)) {
    return false;
  }
  const firstType = first?.constructor.name;
  const secondType = second?.constructor.name;
  if (firstType !== secondType) {
    return false;
  }
  if (firstType === 'Array') {
    if (first.length !== second.length) {
      return false;
    }
    let equal = true;
    for (let i = 0; i < first.length; i++) {
      if (!isEqual(first[i], second[i])) {
        equal = false;
        break;
      }
    }
    return equal;
  }
  if (firstType === 'Object') {
    let equal = true;
    const fKeys = Object.keys(first);
    const sKeys = Object.keys(second);
    if (fKeys.length !== sKeys.length) {
      return false;
    }
    for (let i = 0; i < fKeys.length; i++) {
      if (first[fKeys[i]] && second[fKeys[i]]) {
        if (first[fKeys[i]] === second[fKeys[i]]) {
          continue; // eslint-disable-line
        }
        if (first[fKeys[i]] && (first[fKeys[i]].constructor.name === 'Array'
          || first[fKeys[i]].constructor.name === 'Object')) {
          equal = isEqual(first[fKeys[i]], second[fKeys[i]]);
          if (!equal) {
            break;
          }
        } else if (first[fKeys[i]] !== second[fKeys[i]]) {
          equal = false;
          break;
        }
      } else if ((first[fKeys[i]] && !second[fKeys[i]]) || 
          (!first[fKeys[i]] && second[fKeys[i]])) {
        equal = false;
        break;
      }
    }
    return equal;
  }
  return first === second;
};

console.log(isEqual(array1, array2));    // returns true
```
# References
- [30secondsofcode.org](https://www.30secondsofcode.org/articles/s/javascript-array-comparison)
- [flexiple.com](https://flexiple.com/javascript/javascript-array-equality/)
- [Stack Overflow](https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript)
- [Shubham Jain's gist](https://gist.github.com/jsjain/a2ba5d40f20e19f734a53c0aad937fbb)


