javascript array contains: check values with includes

Explore how to determine whether a javascript array contains a value using includes, predicate-based checks for objects, and edge-case handling like NaN. This practical guide covers primitives, objects, polyfills, and performance considerations.

JavaScripting
JavaScripting Team
·5 min read
Contains Check Essentials - JavaScripting
Quick AnswerDefinition

To check if a JavaScript array contains a value, use Array.prototype.includes for primitives, or a predicate with some for objects. For example, [1,2,3].includes(2) returns true, while [ {id:1}, {id:2} ].includes({id:2}) returns false. For NaN, includes(NaN) correctly returns true due to SameValueZero semantics. If you need deep value matching, use some with a custom comparator.

Understanding javascript array contains

In JavaScript, the concept of contains is implemented primarily through Array.prototype.includes. For primitive values you can rely on a straightforward membership check that returns a boolean. The keyword javascript array contains is why developers reach for includes in everyday coding. This section introduces the core behavior and sets expectations for how different data types behave when tested for containment. The method uses the SameValueZero algorithm, which means that NaN is considered equal to NaN and that -0 and 0 are treated as the same. The result is a clean, readable way to answer the question: does this array contain this value?

JavaScript
const nums = [1, 2, 3, 4]; console.log(nums.includes(2)); // true console.log(nums.includes(5)); // false

Notes:

  • Includes is concise for primitives and avoids the more verbose indexOf pattern.
  • With objects, equality is by reference; two distinct objects with the same shape are not equal.

Choosing the right containment method

While includes is ideal for primitives, you may need indexOf or some for more complex checks. indexOf returns -1 when not found, but some allows a predicate. For example, to find an object with a matching id, you can't rely on includes with object literals; you must provide a comparator function. The example below demonstrates typical usage and limitations.

JavaScript
const people = [{id: 1}, {id: 2}]; console.log(people.includes({id: 2})); // false, different reference console.log(people.some(p => p.id === 2)); // true

Variations:

  • Use indexOf for primitive lists when you only need a simple equality check.
  • Use some with a predicate for complex structures like objects or nested values.

Deep containment: objects and arrays

For arrays of objects, a direct includes check is usually insufficient because objects are compared by reference. The correct approach is to use some with a predicate that compares the relevant properties. This pattern scales to deeper structures by composing predicates or using libraries for deep equality checks safely. Below demonstrates a common pattern across applications.

JavaScript
const users = [{ id: 1, name: 'Ada' }, { id: 2, name: 'Lin' }]; const hasAda = users.some(u => u.name === 'Ada' && u.id === 1); console.log(hasAda); // true

If you frequently search by multiple fields, consider utility helpers or libraries that support deep equality checks safely.

Handling NaN and special values

NaN is a tricky value in JavaScript comparisons. The includes method uses SameValueZero, which means contains(NaN) will return true, unlike some past patterns. Also note that -0 and 0 are considered equal under includes. This section shows the practical implications with quick demos.

JavaScript
const mixed = [NaN, 0, -0, 1]; console.log(mixed.includes(NaN)); // true console.log(mixed.includes(0)); // true

Best practice: rely on includes for NaN cases, and compose predicates for nuanced numeric comparisons when necessary.

Polyfills and browser support

If you need to support older environments that lack Array.prototype.includes, you can provide a small polyfill that delegates to indexOf. A lightweight polyfill keeps behavior consistent for primitives while avoiding code bloat. After including the polyfill, you can confidently use includes in your codebase.

JavaScript
if (!Array.prototype.includes) { Array.prototype.includes = function(searchElement, fromIndex) { return this.indexOf(searchElement, fromIndex) !== -1; }; }

This approach minimizes compatibility issues while maintaining readable code.

Practical examples: primitives and strings

In real-world code you often check membership in lists of primitives or strings. Includes is the idiomatic choice here because it is short and expressive. The following examples show common usage in UI logic, data filtering, and validation tasks.

JavaScript
const fruits = ['apple', 'banana', 'cherry']; console.log(fruits.includes('banana')); // true console.log(fruits.includes('durian')); // false

Strings are compared by exact content; consider trimming input or normalizing case if user-entered data may vary in casing or whitespace.

Performance considerations

For small arrays, includes is fast and readable. When dealing with very large arrays or tight loops, micro-benchmarks can help decide between includes and alternative methods like indexOf or a custom search. In most cases, the difference is negligible, but for hot paths, a predictable approach matters.

JavaScript
const big = Array.from({ length: 100000 }, (_, i) => i); console.time('includes 99999'); big.includes(99999); console.timeEnd('includes 99999'); console.time('indexOf 99999'); big.indexOf(99999); console.timeEnd('indexOf 99999');

When you still need exact performance guidance, run your own benchmarks in your target environment.

Common pitfalls and gotchas

A common mistake is assuming includes works for object equality. Since objects are compared by reference, includes({ id: 2 }) will be false even if an element with the same properties exists. Always use a predicate for object containment. Another pitfall is relying on includes with undefined and null; ensure your dataset handles missing values gracefully.

JavaScript
const items = [{ id: 1 }, { id: 2 }]; console.log(items.includes({ id: 2 })); // false console.log(items.some(x => x.id === 2)); // true

Edge cases: empty arrays return false for any non-null search element, and negative fromIndex values are interpreted relative to the array length.

Adopt a consistent approach: use includes for simple lists of primitives, and use some with predicates for objects and nested values. Document your predicates clearly so teammates understand the exact matching logic. When sharing utilities, consider writing small helper functions like containsId(list, id) to reuse logic across files.

JavaScript
function containsId(list, id) { return list.some(item => item.id === id); }

By embracing these patterns you reduce bugs and improve code readability across frontend projects and data-processing scripts.

Steps

Estimated time: 30-45 minutes

  1. 1

    Identify the data type and containment scenario

    Review the array contents and determine whether you are checking a primitive value, a string, or an object. Decide between includes for primitive values and a predicate-based approach for objects or nested structures.

    Tip: Start with a simple primitive example to validate your understanding before tackling complex objects.
  2. 2

    Choose containment method

    If you are testing a primitive, use includes. For objects, prepare a predicate that compares the fields you care about. Consider indexOf only for straightforward, single-value lists.

    Tip: Always test with edge cases like NaN, undefined, and null to ensure robustness.
  3. 3

    Write and test examples

    Create small, focused examples to verify behavior. Include both positive and negative cases and comment outputs for clarity.

    Tip: Comment clearly to document the intended matching logic.
  4. 4

    Handle edge cases

    Address NaN, -0/0, and complex object comparisons using predicates. Decide whether deep equality is required or a shallow match suffices.

    Tip: Prefer predicate-based checks over equals for complex data.
  5. 5

    Document and optimize

    Add small utility wrappers for common patterns (e.g., containsId). Consider polyfills for older environments and note performance considerations in hot paths.

    Tip: Document chosen patterns to aid future maintenance.
Pro Tip: Use includes for primitives to keep code readable and concise.
Warning: Objects are compared by reference; use a predicate in some when searching by fields.
Note: NaN is treated specially by includes, so includes(NaN) returns true.
Pro Tip: Polyfill includes for older browsers to avoid runtime errors.

Prerequisites

Required

Optional

  • NPM or Yarn for running examples
    Optional
  • Internet access for MDN docs and references
    Optional

Keyboard Shortcuts

ActionShortcut
CopyCopy code snippets or textCtrl+C
PasteInsert copied contentCtrl+V
FindSearch within code or docsCtrl+F
Format DocumentAuto-format your codeCtrl++F
Open Integrated TerminalRun quick node scriptsCtrl+`
Toggle CommentComment/uncomment code blocksCtrl+/

Questions & Answers

What does javascript array contains do?

JavaScript's contains concept is implemented by Array.prototype.includes. It returns a boolean indicating whether the specified value exists in the array. For primitive values, this is straightforward; for objects, containment requires a predicate that compares properties, not references.

JavaScript uses includes to check if an array contains a value. For objects, you need a predicate because objects are compared by reference.

How is includes different from indexOf?

Includes returns a boolean indicating presence, while indexOf returns the index of the first match or -1 if not found. Includes handles NaN as a match due to SameValueZero semantics, whereas indexOf does not reliably find NaN.

Includes gives you true or false. IndexOf tells you the position or -1, and it doesn't handle NaN reliably.

Can includes search for NaN?

Yes. Includes uses SameValueZero, so includes(NaN) returns true if NaN is present in the array.

Yes, includes can find NaN because it uses a special comparison rule called SameValueZero.

How do I search for an object with specific properties?

Use some with a predicate that compares the target properties, for example: list.some(x => x.id === targetId && x.active). Includes alone will not detect a match for objects with the same properties but different references.

For objects, use some with a predicate that checks the properties you care about.

Is includes supported in all browsers?

Includes is supported in all modern browsers and Node.js. For very old environments, a small polyfill is recommended to ensure consistent behavior.

Most modern environments support includes; if you target older browsers, add a polyfill.

What about performance of contains checks?

For typical UI tasks, includes is fast enough and readable. In hot loops with huge arrays, benchmark includes against alternatives for your environment to choose the best approach.

Includes is usually fast, but benchmark for large data in your environment if performance matters.

What to Remember

  • Use includes for simple containment checks in arrays of primitives
  • Use some with a predicate for objects and deep matches
  • NaN is found by includes due to SameValueZero semantics
  • indexOf cannot detect NaN; prefer includes or a predicate
  • Polyfill includes for broader browser support

Related Articles