completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

Searching arrays

Find items and positions by exact value or by a callback condition with indexOf, includes, find, findLast, some, and every.

By the end you can
  • 01
    Search by valueUse indexOf, lastIndexOf, and includes to find an exact value. Avoid the bugs with NaN, objects, and index 0.
  • 02
    Search by testUse find, findIndex, findLast, and findLastIndex when you know a rule, not the exact value.
  • 03
    Ask yes-or-no questionsUse some and every. Explain when they stop early and what they give for an empty array.

What searching an array means

An array is a list of values in order. Each value sits at a numbered position called an index. The first index is 0, the next is 1, and so on.

Searching an array means asking the list a question. There are two kinds of question:

  • Search by value. You already know the exact value, like the string "draft". You ask: "Is it in the list? At which index?"
  • Search by test. You don't know the exact value. You only know a rule, like "the first product that costs more than 20". You ask: "Which item passes this test?"

JavaScript has a method for each kind of question. Some read the list from left to right. Some read it from right to left. Some stop as soon as they know the answer.

Ask a list two questionsPop out in the code editor (opens in a new tab)JavaScript
const cart = ["tea", "bread", "tea"];
console.log(cart.includes("bread"));
console.log(cart.indexOf("tea"));

Line by line:

  1. Line 1 makes a short list called cart. It holds "tea", "bread", and "tea" again.
  2. Line 2 asks a yes-or-no question: is "bread" in the list? It is, so it prints true.
  3. Line 3 asks for a position: where is "tea"? It prints 0, the index of the first "tea".
cart.indexOf("tea"). A card that says tea is the value to look for. An arrow points to a row of three cards: tea at index 0, bread at index 1, tea at index 2. The first tea card is the match, so indexOf returns 0.cart.indexOf("tea")"tea"look for"tea""bread""tea"index 0index 1index 2returns 0
You hand indexOf the exact value to look for. It compares that value with each item, starting at index 0. The first item that is the same value wins, so the answer is 0.
Real-life analogySearching a bookshelf

Picture a shelf of books. If you know the exact title, you read the titles from the left. Then you say "It is in slot 3" or "It is not on the shelf." Sometimes you only need to say yes or no. But if someone asks for "the first book written after 2010", a title is no help. You must check each book against that rule.

In real life: Read the titles from left to right
In JavaScript: indexOf checks indexes from 0 upward
In real life: Say the slot number, or “not here”
In JavaScript: An index such as 2, or -1 for not found
In real life: Only answer “Is it there?”
In JavaScript: includes returns true or false
In real life: Ask for the first book written after 2010
In JavaScript: find runs a test on each item

This lesson uses ideas from earlier lessons:

Each idea is explained again when it shows up.

Which method answers this question?

INTERACTIVE

Read each row as one method. The columns say what you get back, when to use it, and when it stops.

The array search methods side by side
MethodWhat you get backWhen to use itWhen does it stop?
indexOf(value)The first index, or -1.You know the exact value and need its position.At the first match, from the left.
lastIndexOf(value)The last index, or -1.You know the exact value and need its last position.At the first match, from the right.
includes(value)true or false.You know the exact value and only need yes or no. It also finds NaN.At the first match, from the left.
find(callback)The item, or undefined.You need the first item that passes a test.At the first item that passes.
findIndex(callback)The index, or -1.You need the position of the first item that passes.At the first item that passes.
findLast(callback)The item, or undefined.You need the last item that passes, like the newest error.At the first pass, starting from the end.
findLastIndex(callback)The index, or -1.You need the position of the last item that passes.At the first pass, starting from the end.
some(callback)true or false.You ask: does at least one item pass?At the first item that passes.
every(callback)true or false.You ask: do all items pass?At the first item that fails.

Small habits that prevent bugs

  • The callback gets three things: the current item, its index, and the whole array. If you need the position, use findIndex. Don't find the item and then search again for its index.
  • Search methods only read the array. They don't sort it, remove items, or replace items. Keep your callback a simple test that changes nothing.
  • Make values match before an exact search. For example, if stored statuses are lowercase, turn the text a user typed into lowercase before you search.
  • Plan for "not found". find gives undefined, and the index methods give -1. Reading a property of undefined throws an error. So check the result first, or use optional chaining: match?.name gives undefined instead of an error when match is undefined.
  • The callback's answer only needs to be truthy, but a clear comparison is easier to read. Write item.quantity > 1, which is plainly true or false.
  • Each search reads the array from one end, one item at a time. If your code checks the same long list for exact values many times, a Set may be better. A Set is a collection of unique values whose has() check doesn't read every item.

Before you type a method name, decide what kind of answer you need: an exact value's position, a first match, a last match, or just yes or no. Sort the cards below by that answer.

Which method answers this question?
  • Does roles hold the exact string admin?
  • Give me the first product with price > 100.
  • Where is the first product with price > 100?
  • Show the newest log entry whose level is error.
  • At which index is the newest error log?
  • Is any product out of stock?
  • Did every score pass?
  • Where is the exact string draft in statuses?
Try it yourself
0 of 8 correct

Put each question in the group for the kind of answer it needs. Each card's explanation names a good method.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Where you'll use this

You'll search arrays whenever a page holds a list of real data. For example:

  • A shopping cart checks whether an item is already in it before adding another row.
  • A settings form finds the first field that is filled in wrong.
  • A dashboard shows the newest error from a log.
  • A permission check asks whether a user has one needed role, or all needed roles.
One cart, two different questionsPop out in the code editor (opens in a new tab)JavaScript
const cart = [
  { name: "Tea", quantity: 1 },
  { name: "Notebook", quantity: 2 },
];
const hasNotebook = cart.some((item) => item.name === "Notebook");
const firstMany = cart.find((item) => item.quantity > 1);
console.log(hasNotebook, firstMany.name);
  1. Lines 1 to 4 make a cart with one Tea and two Notebooks.
  2. Line 5 uses some to ask: is there a Notebook in the cart? Yes, so hasNotebook is true.
  3. Line 6 uses find to get the first item with a quantity above 1. That is the Notebook item.
  4. Line 7 prints true Notebook.

Neither method changes the cart. That makes them safe to use while a page is being drawn on screen.

Name the result after the question

Start the variable name with the question you are asking:

  • has or is goes well with some, like hasNotebook.
  • all goes well with every, like allPassing.
  • first goes well with find, like firstOut.
  • last goes well with findLast, like lastError.

All the methods in this lesson read the array and give back an answer. Later lessons cover methods that build new arrays, sort arrays, and copy arrays safely.

Common misconceptions

"I can use indexOf as a yes-or-no check."

No. indexOf returns a number, not true or false. Inside an if, the number 0 counts as false and -1 counts as true. So if (arr.indexOf(x)) is wrong both ways: it skips an item found at index 0, and it runs when the item is missing. Use includes, or compare with !== -1.

"find returns all the matches."

No. find returns only the first matching item. Use filter when you need every match. The next lesson teaches filter.

"Two objects that look the same are equal."

No. An exact search asks whether it is the very same object. Search for the object you saved, or use find(obj => obj.id === 1) when you mean "the object whose id is 1".

"every on an empty array should be false."

It is true. every only says false when it finds an item that fails the test. An empty array has no items, so nothing fails.

"findLast needs a different kind of callback."

No. It takes the same kind of callback as find. Only the direction changes: it starts at the last index and moves left.

Practice: search arrays on purpose

5 EXERCISES
Exercise 1 · Warm-upPredict the NaN search

Predict both printed lines before you run the code.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const values = [NaN, "NaN", NaN];
console.log(values.indexOf(NaN));
console.log(values.includes(NaN));

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeFind the first product that is out of stock

    Which product name does this program print?

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const products = [
      { name: "Tea", inStock: true },
      { name: "Tent", inStock: false },
      { name: "Torch", inStock: true },
    ];
    const match = products.find((product) => !product.inStock);
    console.log(match.name);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeCheck that every score passes

      Which boolean does the program print?

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const scores = [72, 88, 61];
      console.log(scores.every((score) => score >= 60));

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · ChallengeFind the newest error in a log

        Which message does this program print?

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const logs = [
          { level: "info", message: "ready" },
          { level: "error", message: "timeout" },
          { level: "error", message: "retry failed" },
        ];
        const latest = logs.findLast((entry) => entry.level === "error");
        console.log(latest.message);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeFix the indexOf bug

          This code should print allowed, because "admin" is in the list at index 0. But it prints nothing. Write a condition that works.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const roles = ["admin", "editor"];
          
          if (roles.indexOf("admin")) {
            console.log("allowed");
          }

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            7 QUESTIONS

            For each question, first ask: does this method give back an index, an item, or a boolean? Try an answer before you read the explanations. Many wrong answers are real bugs people write.

            Lesson quiz · 7 questionsScore: first tries count
            1. Question 1 of 7What do indexOf and lastIndexOf print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const letters = ["a", "b", "a"];
              console.log(letters.indexOf("a"));
              console.log(letters.lastIndexOf("a"));

              Choose an answer to see the explanation.

            2. Question 2 of 7Which method can tell you whether an array holds NaN?

              Choose an answer to see the explanation.

            3. Question 3 of 7What does this find call print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const products = [{ price: 10 }, { price: 30 }, { price: 50 }];
              console.log(products.find((product) => product.price > 20).price);

              Choose an answer to see the explanation.

            4. Question 4 of 7Which method gives -1 when no item passes the test?

              Choose an answer to see the explanation.

            5. Question 5 of 7What do findLast and findLastIndex print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const logs = ["error", "warn", "error"];
              console.log(logs.findLast((level) => level === "error"));
              console.log(logs.findLastIndex((level) => level === "error"));

              Choose an answer to see the explanation.

            6. Question 6 of 7What do some and every print for an empty array?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log([].some(Boolean));
              console.log([].every(Boolean));

              Choose an answer to see the explanation.

            7. Question 7 of 7What is the bug in if (items.indexOf("apple"))?

              Choose an answer to see the explanation.

            Key takeaways

            • indexOf and lastIndexOf give an index, or -1 if the value is not there. includes gives true or false.
            • includes(NaN) finds NaN. indexOf(NaN) never does.
            • An exact search for an object looks for that very object. To match by a property, like an id, use a callback method.
            • find and findIndex stop at the first item that passes the test. findLast and findLastIndex do the same, starting from the end.
            • some asks "at least one?" and every asks "all?". Both stop as soon as they know the answer.
            • Never write if (arr.indexOf(x)). Use includes, or compare the index with -1.

            Remember the one-liner.
            Search by value with indexOf or includes, search by test with find, and ask yes or no with some or every.

            Up next: map, filter & reduce.

            CompleteFrontend Clear concepts. Working examples.