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:
- concat()
- join()
- fill()
- includes()
- indexOf()
- reverse()
- sort()
- splice()
- at()
- copyWithin()
- flat()
- Array.from()
- findLastIndex()
- forEach()
- every()
- entries()
- values()
- toReversed() (creates a reversed copy of the array without modifying the original)
- toSorted() (creates a sorted copy of the array without modifying the original)
- toSpliced() (creates a new array with elements added or removed without modifying the original)
- with() (returns a copy of the array with a specific element replaced)
- Array.fromAsync()
- Array.of()
- map()
- flatMap()
- reduce()
- reduceRight()
- some()
- find()
- findIndex()
- 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;
};
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;
};
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;
};
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;
};
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;
};
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;
};
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;
};
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;
};
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];
};
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;
};
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);
};
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;
};
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;
};
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);
}
}
};
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;
};
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 };
}
};
};
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 };
}
};
};
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;
};
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
};
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;
};
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;
};
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;
};
23. Array.of()
- Algorithm: Direct array creation
- Time Complexity: O(n)
- Creates array from arguments
// Array.of()
Array.myOf = function(...items) {
return items;
};
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;
};
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();
};
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;
};
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;
};
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;
};
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;
};
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;
};
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;
};
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)