JavaScript includes() returns false? Check types and object references

You can see a value in an array, yet includes() returns false. A number displayed on screen may actually be a string, and two objects with matching properties may still be different objects. Checking the comparison itself is more useful than changing values until false disappears.

Start with the element types, then object references, and finally the search position. Each example below runs independently in a browser console or Node.js with support for Array.prototype.includes().


Check whether numbers and strings are mixed

const values = ["2", "10"];
console.log(values.includes(2));
console.log(values.includes("2"));

The outputs are false and true. The array contains the string "2", which does not match the number 2. includes() does not automatically convert elements to the type of the value you are searching for.

For values from forms or APIs, decide whether the data represents a number or a string identifier. Converting every identifier to a number can discard meaningful leading zeros. Keep the input types consistent with what the data means.

Check whether you have the same object reference

const selected = { id: 7 };
const rows = [selected];
console.log(rows.includes({ id: 7 }));
console.log(rows.includes(selected));

These outputs are also false and true. Writing { id: 7 } again creates a different object, even though its property has the same value. Passing selected succeeds because it refers to the object already in the array.

includes() does not walk through an object’s properties to compare its contents. If you reload data from an API or construct a new object, choose whether you need to find that exact object or an element with a matching property.

Use some to search by a property

const rows = [{ id: 7 }, { id: 12 }];
console.log(rows.some(row => row.id === 7));
console.log(rows.some(row => row.id === "7"));

The first result is true because an element has the numeric id 7. The second is false: the callback uses strict equality to compare a number with the string "7".

some() returns true when at least one element passes the supplied test. Here, the test checks only id. If matching ids are not enough for your application, include the other properties that define a match. An explicit test makes the intended comparison clearer than weakening equality just to get a true result.

Remember the NaN difference from indexOf

console.log([NaN].includes(NaN));
console.log([NaN].indexOf(NaN));
console.log([-0].includes(+0));

The outputs are true, -1, and true. includes() uses SameValueZero, which treats NaN as matching NaN. indexOf() does not find NaN in this array and returns -1 to indicate that no index was found. Positive and negative zero match with includes().

For many values, the result resembles strict equality, but treating includes() as always equivalent to === misses the NaN case. Also choose the return value you need: a membership test gives a boolean, while indexOf() gives an index or -1.

Check the second argument’s starting index

const values = [5, 8, 13];
console.log(values.includes(8));
console.log(values.includes(8, 2));

The results are true and false. The second argument, 2, is a zero-based starting index. It makes the search start at 13 in this array, so the 8 at index 1 is never examined. Omitting the second argument starts the search at the beginning.

When a result is unexpected, compare the actual element types, the object reference you passed, and the starting index. That sequence helps you choose a change that matches the data.

If the next step is ordering the array, see sorting numbers while keeping the original array. For strings that look identical but still differ, NFC and NFKC normalization explains another possible source of a mismatch.

References

このブラウザからの自分のアクセスを解析から除外できます。