Mastering Binary Search in JavaScript​: A Quick Guide

By Guilherme Luiz Maia Pinto
Picture of the author
Published on
Binary Search Banner

When working with large datasets, efficiency is key. One of the fundamental algorithms that optimize search operations is binary search. This method significantly reduces the number of comparisons compared to a linear search, making it ideal for sorted arrays.

What is Binary Search?

Binary search is an efficient algorithm that finds an element in a sorted array by repeatedly dividing the search space in half. It operates in O(log n) time complexity, making it much faster than a linear search (O(n)).

How Does It Work?

  1. Find the middle element of the array.

  2. If it matches the target, return the index.

  3. If the target is smaller, repeat the search in the left half.

  4. If the target is larger, repeat the search in the right half.

  5. Repeat until the element is found or the search space is empty.


JavaScript Example

Here’s a simple implementation of binary search in JavaScript:

  function binarySearch(nums: number[], target: number): number {
    let minimum = 0
    let maximum = nums.length - 1

    while (minimum <= maximum) {
        const mid = (minimum + maximum) / 2 | 0
        const possible = nums[mid]
        
        if(possible === target) {
            return mid
        } else if (possible < target) {
            minimum = mid + 1
        } else {
            maximum = mid - 2
        }
    }

      return -1
  };

  const testArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  const testTarget = 5

  console.log(binarySearch(testArray, testTarget))

Why Use Binary Search?

  • Speed: Works in logarithmic time, making it highly efficient for large datasets.

  • Simplicity: Easy to implement with recursion or iteration.

  • Real-World Usage: Used in databases, search engines, and even gaming for optimizing searches.


Preconditions and Data Requirements

Binary search only works on a sorted collection. If the array is not sorted, the algorithm will not give correct results. The most common case is an array sorted in ascending order, but it also works for descending order if you invert the comparison logic. Elements must be comparable so you can tell whether the middle value is smaller or larger than the target.

If you are searching in a list of objects, decide the comparison key first (for example, compare by id or by name) and keep the list sorted by that key.


Walkthrough Example

Consider the array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and the target 7.

  1. Minimum is 0, maximum is 9. Middle index is (0 + 9) / 2 | 0 = 4. Value is 5. Since 5 < 7, move to the right half.
  2. Minimum becomes 5, maximum stays 9. Middle is (5 + 9) / 2 | 0 = 7. Value is 8. Since 8 > 7, move to the left half.
  3. Minimum stays 5, maximum becomes 6. Middle is (5 + 6) / 2 | 0 = 5. Value is 6. Since 6 < 7, move to the right half.
  4. Minimum becomes 6, maximum stays 6. Middle is (6 + 6) / 2 | 0 = 6. Value is 7. We found the target at index 6.

This small example shows how the search space is divided quickly and why the algorithm is efficient.


Edge Cases and Common Mistakes

  • Empty array: return -1 immediately because there is nothing to search.
  • Single element: check the only element and return 0 if it matches, otherwise -1.
  • Off-by-one errors: make sure the loop condition allows checking both ends (minimum <= maximum).
  • Infinite loop: always move one of the bounds after comparing the middle element; otherwise, the same middle may repeat.
  • Mid calculation: in very large arrays, some languages can overflow when computing (minimum + maximum) / 2. A safer variant is minimum + Math.floor((maximum - minimum) / 2). JavaScript numbers reduce this risk, but the pattern is still good practice.

Variations You Will Use Often

  • First occurrence (lower bound): when the array has duplicates, you may want the first index where the value appears.
  • Last occurrence (upper bound): similar idea, but for the final position of the target.
  • Insertion index: if the target is not found, return the position where it should be inserted to keep the array sorted. This is useful in auto-complete, ranking, or maintaining ordered lists.

These variants are small changes to the comparison and how you update the bounds, but they are very useful in real projects.


When to Use or Avoid

Use binary search for large, sorted datasets when you need fast lookups. It shines when reads are frequent and writes are rare. If the collection is small, a simple linear search might be enough and easier to maintain. If the data changes often and needs re-sorting, consider the cost of keeping it sorted versus the speed gains from faster searches.


Complexity and Practical Notes

  • Time complexity: O(log n) because the search space halves each step.
  • Space complexity: O(1) for an iterative approach. Recursive versions may use O(log n) stack space.
  • Practice tip: test with arrays of even and odd lengths, with targets at the start, middle, end, and with values that do not exist.

Understanding these details helps you adapt the basic idea to many daily tasks: searching in logs, finding thresholds in performance data, or selecting ranges in user interfaces.


Here's the code on GitHub.

Want to practice? Try this related exercise on LeetCode.

Stay Tuned

Want to become a Software Engineer pro?
The best articles and links related to web development are delivered once a week to your inbox.