How to actually find array inside array javascript without losing your mind

How to actually find array inside array javascript without losing your mind

JavaScript is weird. Honestly, it’s one of the most frustrating things about the language when you first hit a wall with referential integrity. You’ve got a big list of data, and you’re trying to find array inside array javascript style, but indexOf keeps returning -1 even though you can literally see the data right there on your screen. It feels like the language is gaslighting you.

It’s not broken, though. It’s just how memory works.

When you compare two strings like "apple" and "apple," JavaScript says, "Yeah, those are the same." But when you compare [1, 2] and [1, 2], JavaScript looks at them and says, "Nope, totally different." To the engine, these are two different physical objects sitting in different spots in your computer’s RAM. If you want to find a specific sub-array within a larger nested structure, you have to stop looking at the container and start looking at the contents.

Why your basic search methods are failing you

Most people start with Array.prototype.indexOf() or Array.prototype.includes(). It makes sense. If you have an array of numbers, those methods work like a charm. But the second you nest arrays, you're dealing with "shallow" comparisons.

🔗 Read more: The Build Is On Fire: Why Developers Are Bracing for the 2026 AI Infrastructure Crash

Basically, JavaScript checks if the reference is the same. Unless you are searching for the exact same variable instance that you stored earlier, these built-in methods will fail every single time.

Imagine you have a grid: const grid = [[0, 1], [2, 3], [4, 5]];.
If you try grid.includes([0, 1]), it returns false.
Why? Because the [0, 1] you just typed into the function is a brand-new array, created on the fly. It doesn’t matter that it has the same numbers. It’s a different "house" with the same furniture.

The JSON stringify "hack" and why it's risky

You'll see a lot of developers on Stack Overflow suggest JSON.stringify(). The logic is simple: convert both arrays into strings and compare the strings.

const haystack = [[1, 2], [3, 4], [5, 6]];
const needle = [3, 4];
const found = haystack.some(item => JSON.stringify(item) === JSON.stringify(needle));

It works. Sorta.

It’s fast to write, but it’s dangerously brittle. What happens if your array has undefined? JSON skips it. What if the keys in an object inside that array are in a different order? The strings won't match, even if the data is functionally identical. Also, stringifying large datasets inside a loop is a performance nightmare. It’s like printing out two entire books just to see if page 50 has the same sentence.

If you want to find array inside array javascript correctly, you need to use .find() or .findIndex() in combination with .every(). This is the professional way to do it. You’re essentially telling the computer: "Look at every sub-array, and for each one, check if every single element matches my target."

Here is how that looks in the real world:

const data = [[10, 20], [30, 40], [50, 60]];
const target = [30, 40];

const exists = data.find(subArray => 
  subArray.length === target.length && 
  subArray.every((value, index) => value === target[index])
);

Check the length first. It's a tiny optimization, but if the lengths don't match, there is no point in checking the values. It saves time. This approach is robust because it compares the actual values inside the memory blocks rather than the addresses of the blocks themselves.

Dealing with multi-dimensional messiness

Sometimes it isn't just a list of pairs. Sometimes you’re looking through a 3D coordinate system or a complex state tree in React. When you get deeper than one level, .every() starts to look a bit messy.

At this point, you should probably be looking at recursion. If you don't know how deep the nesting goes, a recursive function can "drill down" until it hits the primitive values (like strings or numbers) and then bubble the result back up. But honestly? For 90% of web development tasks, you’re just looking for a coordinate or a pair of IDs. Keep it simple. Don't over-engineer a solution for a problem you don't have yet.

Performance matters more than you think

If you are running this search on an array with 100,000 items inside a requestAnimationFrame loop, your site is going to lag. Hard.

In high-performance scenarios, you might want to "flatten" your data or use a Map where the keys are a string representation of the array. This gives you O(1) lookup time instead of O(n).

What about Lodash or Underscore?

Years ago, we used Lodash for everything. _.isEqual was the gold standard. Today? You probably don't need it. Modern JavaScript has evolved enough that pulling in a whole library just to compare two arrays is usually overkill. However, if you're already using Lodash in your project, _.some(haystack, _.partial(_.isEqual, needle)) is incredibly readable.

Readable code is often better than "clever" code. If a junior developer joins your team and sees a nested .every() inside a .find(), they might take a second to parse it. If they see isEqual, they know exactly what's happening.

Common pitfalls to avoid

  1. Strict Equality: Remember that == and === behave differently, but for array elements, you almost always want ===.
  2. Empty Arrays: Comparing [] === [] is false. Always remember the reference rule.
  3. Sparse Arrays: If your array has holes (e.g., [1, , 3]), .every() might behave in ways you don't expect.

Real-world use case: Map Coordinates

Let's say you're building a game or a mapping tool. You have a list of "visited" coordinates, and you need to check if the user's current position [x, y] is in that list.

const visitedSquares = [[0, 0], [0, 1], [1, 1]];
const currentPos = [0, 1];

const hasVisited = visitedSquares.some(coord => 
    coord[0] === currentPos[0] && coord[1] === currentPos[1]
);

This is the most performant way because you aren't looping through an unknown number of elements; you know exactly there are only two (x and y). You're hard-coding the index check. It’s lightning-fast.

Actionable Steps for your code

If you need to implement this right now, follow these steps to ensure it doesn't break:

  • Validate your input: Ensure the "needle" and the "haystack" are actually arrays before calling methods on them. Use Array.isArray().
  • Determine depth: If you only have one level of nesting, stick with .some() and .every().
  • Check for reference stability: If you can control how the arrays are created, try to keep a reference to the original array. If you find the exact same object, includes() will actually work.
  • Consider a Set: If you are frequently checking if an array exists in a collection, convert your arrays to strings and store them in a Set. mySet.has(JSON.stringify(currentArray)) is much faster for frequent lookups.

Stop trying to make indexOf happen for nested arrays. It’s not going to happen. Stick to value-based comparison and your code will actually work the way you expect it to.