Implementing JavaScript Array Methods From Scratch
Further reading: If
thisArgor mounting onprototypefeels fuzzy, it helps to understandthisbinding and the prototype chain first:
1.Master call, apply, bind in Three Sentences
1.Arrow Functions and this β From First Principles to Practice
1.The Prototype Chain β How new Creates Objects and Enables Method Sharing
forEach
Invokes a provided function once per array element.
arr.forEach(callback(element, index, array), thisArg)
Array.prototype.myForEach = function (callback, thisArg) {
for (let i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
Straightforward traversal; key nuance is binding thisArg via call().
map
Returns a new array populated with the results of calling a provided function on every element.
arr.map(callback(element, index, array), thisArg)
Array.prototype.myMap = function (callback, thisArg) {
const result = new Array(this.length);
for (let i = 0; i < this.length; i++) {
result[i] = callback.call(thisArg, this[i], i, this);
}
return result;
};
Pre-allocate the result array to the same length, then fill by mapping each element.
filter
Returns a new array with all elements that pass the test implemented by the provided function.
arr.filter(callback(element, index, array), thisArg)
Array.prototype.myFilter = function (callback, thisArg) {
const result = [];
for (let i = 0; i < this.length; i++) {
if (callback.call(thisArg, this[i], i, this)) {
result.push(this[i]);
}
}
return result;
};
Iterate and conditionally collect; only elements that satisfy the predicate are pushed.
reduce
Executes a reducer function on each element, resulting in a single output value.
arr.reduce(callback(accumulator, currentValue, index, array), initialValue)
Array.prototype.myReduce = function (callback, initialValue) {
let acc, startIndex;
if (arguments.length >= 2) {
acc = initialValue;
startIndex = 0;
} else {
acc = this[0];
startIndex = 1;
}
for (let i = startIndex; i < this.length; i++) {
acc = callback(acc, this[i], i, this);
}
return acc;
};
Accumulate via a reducer; arguments.length distinguishes βno initial valueβ from an explicit undefined.