DEV Community

Nozibul Islam
Nozibul Islam

Posted on

Algorithms Behind JavaScript Array Methods

Algorithms Behind JavaScript Array Methods.

JavaScript arrays come with various built-in methods that allow manipulation and retrieval of data in an array. Here’s a list of array methods extracted from your outline:

  1. concat()
  2. join()
  3. fill()
  4. includes()
  5. indexOf()
  6. reverse()
  7. sort()
  8. splice()
  9. at()
  10. copyWithin()
  11. flat()
  12. Array.from()
  13. findLastIndex()
  14. forEach()
  15. every()
  16. entries()
  17. values()
  18. toReversed() (creates a reversed copy of the array without modifying the original)
  19. toSorted() (creates a sorted copy of the array without modifying the original)
  20. toSpliced() (creates a new array with elements added or removed without modifying the original)
  21. with() (returns a copy of the array with a specific element replaced)
  22. Array.fromAsync()
  23. Array.of()
  24. map()
  25. flatMap()
  26. reduce()
  27. reduceRight()
  28. some()
  29. find()
  30. findIndex()
  31. findLast()

Let me break down the common algorithms used for each JavaScript array method:

1. concat()

  • Algorithm: Linear append/merge
  • Time Complexity: O(n) where n is total length of all arrays
  • Internally uses iteration to create new array and copy elements
// concat()
Array.prototype.myConcat = function(...arrays) {
  const result = [...this];
  for (const arr of arrays) {
    for (const item of arr) {
      result.push(item);
    }
  }
  return result;
};
Enter fullscreen mode Exit fullscreen mode

2. join()

  • Algorithm: Linear traversal with string concatenation
  • Time Complexity: O(n)
  • Iterates through array elements and builds result string
// join()
Array.prototype.myJoin = function(separator = ',') {
  let result = '';
  for (let i = 0; i < this.length; i++) {
    result += this[i];
    if (i < this.length - 1) result += separator;
  }
  return result;
};
Enter fullscreen mode Exit fullscreen mode

3. fill()

  • Algorithm: Linear traversal with assignment
  • Time Complexity: O(n)
  • Simple iteration with value assignment
// fill()
Array.prototype.myFill = function(value, start = 0, end = this.length) {
  for (let i = start; i < end; i++) {
    this[i] = value;
  }
  return this;
};
Enter fullscreen mode Exit fullscreen mode

4. includes()

  • Algorithm: Linear search
  • Time Complexity: O(n)
  • Sequential scan until element found or end reached
// includes()
Array.prototype.myIncludes = function(searchElement, fromIndex = 0) {
  const startIndex = fromIndex >= 0 ? fromIndex : Math.max(0, this.length + fromIndex);
  for (let i = startIndex; i < this.length; i++) {
    if (this[i] === searchElement || (Number.isNaN(this[i]) && Number.isNaN(searchElement))) {
      return true;
    }
  }
  return false;
};
Enter fullscreen mode Exit fullscreen mode

5. indexOf()

  • Algorithm: Linear search
  • Time Complexity: O(n)
  • Sequential scan from start until match found
// indexOf()
Array.prototype.myIndexOf = function(searchElement, fromIndex = 0) {
  const startIndex = fromIndex >= 0 ? fromIndex : Math.max(0, this.length + fromIndex);
  for (let i = startIndex; i < this.length; i++) {
    if (this[i] === searchElement) return i;
  }
  return -1;
};
Enter fullscreen mode Exit fullscreen mode

6. reverse()

  • Algorithm: Two-pointer swap
  • Time Complexity: O(n/2)
  • Swaps elements from start/end moving inward
// reverse()
Array.prototype.myReverse = function() {
  let left = 0;
  let right = this.length - 1;

  while (left < right) {
    // Swap elements
    const temp = this[left];
    this[left] = this[right];
    this[right] = temp;
    left++;
    right--;
  }

  return this;
};
Enter fullscreen mode Exit fullscreen mode

7. sort()

  • Algorithm: Typically TimSort (hybrid of merge sort and insertion sort)
  • Time Complexity: O(n log n)
  • Modern browsers use adaptive sorting algorithms
// sort()
Array.prototype.mySort = function(compareFn) {
  // Implementation of QuickSort for simplicity
  // Note: Actual JS engines typically use TimSort
  const quickSort = (arr, low, high) => {
    if (low < high) {
      const pi = partition(arr, low, high);
      quickSort(arr, low, pi - 1);
      quickSort(arr, pi + 1, high);
    }
  };

  const partition = (arr, low, high) => {
    const pivot = arr[high];
    let i = low - 1;

    for (let j = low; j < high; j++) {
      const compareResult = compareFn ? compareFn(arr[j], pivot) : String(arr[j]).localeCompare(String(pivot));
      if (compareResult <= 0) {
        i++;
        [arr[i], arr[j]] = [arr[j], arr[i]];
      }
    }
    [arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
    return i + 1;
  };

  quickSort(this, 0, this.length - 1);
  return this;
};
Enter fullscreen mode Exit fullscreen mode

8. splice()

  • Algorithm: Linear array modification
  • Time Complexity: O(n)
  • Shifts elements and modifies array in-place
// splice()
Array.prototype.mySplice = function(start, deleteCount, ...items) {
  const len = this.length;
  const actualStart = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
  const actualDeleteCount = Math.min(Math.max(deleteCount || 0, 0), len - actualStart);

  // Store deleted elements
  const deleted = [];
  for (let i = 0; i < actualDeleteCount; i++) {
    deleted[i] = this[actualStart + i];
  }

  // Shift elements if necessary
  const itemCount = items.length;
  const shiftCount = itemCount - actualDeleteCount;

  if (shiftCount > 0) {
    // Moving elements right
    for (let i = len - 1; i >= actualStart + actualDeleteCount; i--) {
      this[i + shiftCount] = this[i];
    }
  } else if (shiftCount < 0) {
    // Moving elements left
    for (let i = actualStart + actualDeleteCount; i < len; i++) {
      this[i + shiftCount] = this[i];
    }
  }

  // Insert new items
  for (let i = 0; i < itemCount; i++) {
    this[actualStart + i] = items[i];
  }

  this.length = len + shiftCount;
  return deleted;
};
Enter fullscreen mode Exit fullscreen mode

9. at()

  • Algorithm: Direct index access
  • Time Complexity: O(1)
  • Simple array indexing with boundary checking
// at()
Array.prototype.myAt = function(index) {
  const actualIndex = index >= 0 ? index : this.length + index;
  return this[actualIndex];
};
Enter fullscreen mode Exit fullscreen mode

10. copyWithin()

  • Algorithm: Block memory copy
  • Time Complexity: O(n)
  • Internal memory copy and shift operations
// copyWithin()
Array.prototype.myCopyWithin = function(target, start = 0, end = this.length) {
  const len = this.length;
  let to = target < 0 ? Math.max(len + target, 0) : Math.min(target, len);
  let from = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
  let final = end < 0 ? Math.max(len + end, 0) : Math.min(end, len);
  const count = Math.min(final - from, len - to);

  // Copy to temporary array to handle overlapping
  const temp = new Array(count);
  for (let i = 0; i < count; i++) {
    temp[i] = this[from + i];
  }

  for (let i = 0; i < count; i++) {
    this[to + i] = temp[i];
  }

  return this;
};

Enter fullscreen mode Exit fullscreen mode

11. flat()

  • Algorithm: Recursive depth-first traversal
  • Time Complexity: O(n) for single level, O(d*n) for depth d
  • Recursively flattens nested arrays
// flat()
Array.prototype.myFlat = function(depth = 1) {
  const flatten = (arr, currentDepth) => {
    const result = [];
    for (const item of arr) {
      if (Array.isArray(item) && currentDepth < depth) {
        result.push(...flatten(item, currentDepth + 1));
      } else {
        result.push(item);
      }
    }
    return result;
  };

  return flatten(this, 0);
};
Enter fullscreen mode Exit fullscreen mode

12. Array.from()

  • Algorithm: Iteration and copy
  • Time Complexity: O(n)
  • Creates new array from iterable
// Array.from()
Array.myFrom = function(arrayLike, mapFn) {
  const result = [];
  for (let i = 0; i < arrayLike.length; i++) {
    result[i] = mapFn ? mapFn(arrayLike[i], i) : arrayLike[i];
  }
  return result;
};
Enter fullscreen mode Exit fullscreen mode

13. findLastIndex()

  • Algorithm: Reverse linear search
  • Time Complexity: O(n)
  • Sequential scan from end until match found
// findLastIndex()
Array.prototype.myFindLastIndex = function(predicate) {
  for (let i = this.length - 1; i >= 0; i--) {
    if (predicate(this[i], i, this)) return i;
  }
  return -1;
};
Enter fullscreen mode Exit fullscreen mode

14. forEach()

  • Algorithm: Linear iteration
  • Time Complexity: O(n)
  • Simple iteration with callback execution
// forEach()
Array.prototype.myForEach = function(callback) {
  for (let i = 0; i < this.length; i++) {
    if (i in this) {  // Skip holes in sparse arrays
      callback(this[i], i, this);
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

15. every()

Algorithm: Short-circuit linear scan
Time Complexity: O(n)
Stops on first false condition

// every()
Array.prototype.myEvery = function(predicate) {
  for (let i = 0; i < this.length; i++) {
    if (i in this && !predicate(this[i], i, this)) {
      return false;
    }
  }
  return true;
};
Enter fullscreen mode Exit fullscreen mode

16. entries()

  • Algorithm: Iterator protocol implementation
  • Time Complexity: O(1) for creation, O(n) for full iteration
  • Creates iterator object
// entries()
Array.prototype.myEntries = function() {
  let index = 0;
  const array = this;

  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      if (index < array.length) {
        return { value: [index, array[index++]], done: false };
      }
      return { done: true };
    }
  };
};
Enter fullscreen mode Exit fullscreen mode

17. values()

  • Algorithm: Iterator protocol implementation
  • Time Complexity: O(1) for creation, O(n) for full iteration
  • Creates iterator for values
// values()
Array.prototype.myValues = function() {
  let index = 0;
  const array = this;

  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      if (index < array.length) {
        return { value: array[index++], done: false };
      }
      return { done: true };
    }
  };
};
Enter fullscreen mode Exit fullscreen mode

18. toReversed()

  • Algorithm: Copy with reverse iteration
  • Time Complexity: O(n)
  • Creates new reversed array
// toReversed()
Array.prototype.myToReversed = function() {
  const result = new Array(this.length);
  for (let i = 0; i < this.length; i++) {
    result[i] = this[this.length - 1 - i];
  }
  return result;
};
Enter fullscreen mode Exit fullscreen mode

19. toSorted()

  • Algorithm: Copy then TimSort
  • Time Complexity: O(n log n)
  • Creates sorted copy using standard sort
// toSorted()
Array.prototype.myToSorted = function(compareFn) {
  return [...this].mySort(compareFn); // Reuse mySort implementation
};
Enter fullscreen mode Exit fullscreen mode

20. toSpliced()

  • Algorithm: Copy with modification
  • Time Complexity: O(n)
  • Creates modified copy
// toSpliced()
Array.prototype.myToSpliced = function(start, deleteCount, ...items) {
  const result = [...this];
  result.mySplice(start, deleteCount, ...items);  // Reuse mySplice implementation
  return result;
};
Enter fullscreen mode Exit fullscreen mode

21. with()

  • Algorithm: Shallow copy with single modification
  • Time Complexity: O(n)
  • Creates copy with one element changed
// with()
Array.prototype.myWith = function(index, value) {
  const result = [...this];
  result[index < 0 ? this.length + index : index] = value;
  return result;
};
Enter fullscreen mode Exit fullscreen mode

22. Array.fromAsync()

  • Algorithm: Asynchronous iteration and collection
  • Time Complexity: O(n) + async operations
  • Handles promises and async iterables
// Array.fromAsync()
Array.myFromAsync = async function(asyncIterable) {
  const result = [];
  for await (const item of asyncIterable) {
    result.push(item);
  }
  return result;
};
Enter fullscreen mode Exit fullscreen mode

23. Array.of()

  • Algorithm: Direct array creation
  • Time Complexity: O(n)
  • Creates array from arguments
// Array.of()
Array.myOf = function(...items) {
  return items;
};
Enter fullscreen mode Exit fullscreen mode

24. map()

  • Algorithm: Transform iteration
  • Time Complexity: O(n)
  • Creates new array with transformed elements
// map()
Array.prototype.myMap = function(callback) {
  const result = new Array(this.length);
  for (let i = 0; i < this.length; i++) {
    if (i in this) {  // Skip holes in sparse arrays
      result[i] = callback(this[i], i, this);
    }
  }
  return result;
};
Enter fullscreen mode Exit fullscreen mode

25. flatMap()

  • Algorithm: Map + flatten
  • Time Complexity: O(n*m) where m is average mapped array size
  • Combines mapping and flattening
// flatMap()
Array.prototype.myFlatMap = function(callback) {
  return this.myMap(callback).myFlat();
};
Enter fullscreen mode Exit fullscreen mode

26. reduce()

  • Algorithm: Linear accumulation
  • Time Complexity: O(n)
  • Sequential accumulation with callback
// reduce()
Array.prototype.myReduce = function(callback, initialValue) {
  let accumulator = initialValue;
  let startIndex = 0;

  if (initialValue === undefined) {
    if (this.length === 0) throw new TypeError('Reduce of empty array with no initial value');
    accumulator = this[0];
    startIndex = 1;
  }

  for (let i = startIndex; i < this.length; i++) {
    if (i in this) {
      accumulator = callback(accumulator, this[i], i, this);
    }
  }

  return accumulator;
};
Enter fullscreen mode Exit fullscreen mode

27. reduceRight()

  • Algorithm: Reverse linear accumulation
  • Time Complexity: O(n)
  • Right-to-left accumulation
// reduceRight()
Array.prototype.myReduceRight = function(callback, initialValue) {
  let accumulator = initialValue;
  let startIndex = this.length - 1;

  if (initialValue === undefined) {
    if (this.length === 0) throw new TypeError('Reduce of empty array with no initial value');
    accumulator = this[this.length - 1];
    startIndex = this.length - 2;
  }

  for (let i = startIndex; i >= 0; i--) {
    if (i in this) {
      accumulator = callback(accumulator, this[i], i, this);
    }
  }

  return accumulator;
};
Enter fullscreen mode Exit fullscreen mode

28. some()

  • Algorithm: Short-circuit linear scan
  • Time Complexity: O(n)
  • Stops on first true condition
// some()
Array.prototype.mySome = function(predicate) {
  for (let i = 0; i < this.length; i++) {
    if (i in this && predicate(this[i], i, this)) {
      return true;
    }
  }
  return false;
};
Enter fullscreen mode Exit fullscreen mode

29. find()

  • Algorithm: Linear search
  • Time Complexity: O(n)
  • Sequential scan until condition met
// find()
Array.prototype.myFind = function(predicate) {
  for (let i = 0; i < this.length; i++) {
    if (i in this && predicate(this[i], i, this)) {
      return this[i];
    }
  }
  return undefined;
};
Enter fullscreen mode Exit fullscreen mode

30. findIndex()

  • Algorithm: Linear search
  • Time Complexity: O(n)
  • Sequential scan for matching condition
// findIndex()
Array.prototype.myFindIndex = function(predicate) {
  for (let i = 0; i < this.length; i++) {
    if (i in this && predicate(this[i], i, this)) {
      return i;
    }
  }
  return -1;
};
Enter fullscreen mode Exit fullscreen mode

31. findLast()

  • Algorithm: Reverse linear search
  • Time Complexity: O(n)
  • Sequential scan from end
// findLast()
Array.prototype.myFindLast = function(predicate) {
  for (let i = this.length - 1; i >= 0; i--) {
    if (i in this && predicate(this[i], i, this)) {
      return this[i];
    }
  }
  return undefined;
};
Enter fullscreen mode Exit fullscreen mode

I've provided complete implementations of all 31 array methods you requested.

🔗 Connect with me on LinkedIn:

Let’s dive deeper into the world of software engineering together! I regularly share insights on JavaScript, TypeScript, Node.js, React, Next.js, data structures, algorithms, web development, and much more. Whether you're looking to enhance your skills or collaborate on exciting topics, I’d love to connect and grow with you.

Follow me: Nozibul Islam

Top comments (0)