Introduction
Arrays in JavaScript are a special type of object which is mutable and can store multiple values. Underneath it is implemented as a Class
which has methods to mutate array in its prototypes. We’ll be looking at some of the methods in this post and implementing them on our own. These implementation doesn’t change existing methods but provides a way to add our methods to them.
- map
- forEach
- filter
- reduce
- reverse
Let’s understand what prototypes are and how we can use them here to create methods.
Prototypes
Every function and Object in JavaScript has a property named prototype
. It consists of methods available on Object. It inherits them from the Object that is created. If we have to add more methods to an Object we add them as follows:
function Person() {
this.name = "John"
this.age = 26
}
Person.prototype.emailId = "john@doe.com"
Person.prototype.getContact = function() {
return {name: this.name, email: this.emailId }
}
const p1 = new Person()
console.log(p1.getName())
// Output: { name: "John", email: "john@doe.com" }
this
in function carries a value of properties available in the object. So whatever methods or properties a function/object can have, we can access them using this.
Implementing array methods
We’ll be using the above technique to add our custom methods to the array class. Since arrays are a global object, we can use this
to get the array we are manipulating.
map
Array.prototype.myCustomMap = function map(callback) {
const results = [];
for (let i = 0; i < this.length; i++) {
results.push(callback(this[i], i, this));
}
return results;
}
const input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const output = input.myCustomMap(elem => {
return 3*elem;
});
console.log(output); // [ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30]
In the implementation above, we created myCustomMap
method on Array. It takes the callback
function as a parameter which takes the old value as an argument and returns a new value. We use the same index to store the new value in the results array.
forEach
Array.prototype.myCustomForEach = function (callback) {
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this);
}
}
const input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
input.myCustomForEach(elem => {
console.log(elem);
}); // 1 2 3 4 5 6 7 8 9 10
In the implementation above, we created myCustomForEach
method that takes callback
function as a parameter and iterates over elements of the array without returning anything. It returns undefined, unlike map method.
filter
Array.prototype.myCustomFilter = function (callback) {
const results = [];
for (let i = 0; i < this.length; i++) {
if(callback(this[i], i, this))
results.push(this[i]);
}
return results;
}
let input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const output = input.myCustomFilter((elem) => {
return elem % 2 === 0;
});
console.log(output); // [ 2, 4, 6, 8, 10 ]
In the implementation above, we created myCustomFilter
method which takes callback function as a parameter and performs the callback function and for the values that is true, we return the result in new array. We return new array with elements by pushing elements without keeping them at same index.
reduce
The reduce
function iterates through each element of the array and returns a single value. According to MDN docs, the first time that the callback is run there is no "return value of the previous calculation". If supplied, an initial value may be used in its place. Otherwise, the array element at index 0 is used as the initial value and iteration starts from the next element (index 1 instead of index 0).
// Syntax
reduce(function(previousValue, currentValue){/* ... */}, initialValue)
Array.prototype.myCustomReduce = function (callback, initialValue) {
let value = initialValue;
for (let i = 0; i < this.length; i++) {
value = callback(value, this[i]);
}
return value;
}
const input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const sum = input.myCustomReduce((acc, elem) => {
// acc stores value of previous return
return acc + elem;
}, 0);
console.log(sum); // 55
reverse
Array.prototype.myCustomReverse = function () {
const result = [];
const lastIndex = array.length - 1;
for (let index = lastIndex; index > -1; index -= 1) {
const value = array[index];
result[lastIndex - index] = value;
}
return result;
}
const input = [1, 'b', 'abc', { name: 'Jonh' }, 10];
console.log(input.myCustomReverse()); // [10, { name: 'Jonh' }, 'abc', 'b', 1]
In the reverse method, we iterate over the array in reverse, saving each value at [lastIndex - index]
place in result
array, which can be returned.
Conclusion
There is no better way to understand or learn something until we know how it works underneath. We have discussed how methods of arrays work internally, we can use them efficiently for our use-cases. I haven’t discussed sort
in this post because implementing sort is a bit complicated for beginners. I’ll be covering it in a separate post.