Reimplementing JavaScript Array methods

Dominik Bulaj
4 min readMay 5, 2020

--

Some time ago I’ve found list of JavaScript tasks. Those cover all developer career levels — Newbie/Junior/Mid and are fun way to practice programming.
NOTE those tasks are written in Polish language but I’m gonna translate task requirements to English :)

I’ve decided to give it a try and reimplement some of commonly used JavaScript Array methods.

Task says:

// Task #6 —Array methods
// as JS is functional language it’s worth mastering its basic methods

// .map
// .filter
// .reduce
// .reduceRight
// .every
// .some
// .entries

// Create functions that will work same way as original Array methods. Functions has to use for or while loops

We got also function signatures:

function mapFn(array, callback){}function filterFn(array, callback){}function reduceFn(array, callback, initial){}function reduceRightFn(array, callback, initial){}function everyFn(array, callback){}function someFn(array, callback){}function entriesFn(array){}

Easy, right?
Let’s check…

Array.map()

The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

That was easy to build. All we need is to execute callback function on each array element and return value into new array. When finished iterating over elements — return new array. Pretty easy…

function mapFn(array, callback) {
const out = [];
for (let i of array) {
out.push(callback(i));
}
return out;
}

Array.filter()

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Again, nothing fancy here. We need to create new array and push there elements only if callback’s test is passed:

function filterFn(array, callback) {
const out = [];
for (let i of array) {
callback(i) && out.push(i);
}
return out;
}

Array.reduce()

The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Reduce, required a bit more work. Callback accepts up to 4 parameters, and function itself can have (optional) initial value. If initial value is omitted we need to take 1st array element instead of.

Callback functions takes up to 4 parameters:

  1. accumulator (accumulates callback’s return value)
  2. currentValue (current array element value)
  3. (optional) index (current array index)
  4. (optional) array (complete entry array)
function reduceFn(array, callback, initial) {
let out = initial;
for (let i in array) {
// in case initial value is missing we take 1st element of an array
if (out === undefined) {
out = array[i];
continue;
}
out = callback(out, array[i], i, array);
}
return out;
}

Array.reduceRight()

The reduceRight() method applies a function against an accumulator and each value of the array (from right-to-left) to reduce it to a single value.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight

It is similar function to previous one but it starts executing callback from right (from the end — highest array index to lowest one).

Similar to Array.reduce() initial value can be omitted — in such a case we need to take last array element as it.

function reduceRightFn(array, callback, initial) {
let index = array.length;
let out = initial;
while (--index > -1) {
// in case initial value is missing we take last element of an array
if (out === undefined) {
out = array[index];
continue;
}
out = callback(out, array[index], index, array);
}
return out;
}

Array.every()

The every() method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every

According to the description we need to build function that checks if every element in array passes callback test. That means if at least one check won’t pass — we need return false. That’s all!

function everyFn(array, callback) {
for (let i of array) {
if (!callback(i)) {
return false;
}
}
return true;
}

That simple solution also covers special case:

Caution: Calling this method on an empty array will return true for any condition!

Array.some()

The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns a Boolean value.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some

As you can see Array.some() is similar to Array.every() the difference is subtle — we got truthy response as soon as at least one element passes callback test.

function someFn(array, callback) {
for (let i of array) {
if (callback(i)) {
return true;
}
}
return false;
}

Again, special case is covered:

Caution: Calling this method on an empty array returns false for any condition!

Array.entries()

The entries() method returns a new Array Iterator object that contains the key/value pairs for each index in the array.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries

That was most challenging for me. Most probably because I rarely create custom iterators or work with generators…

Even though I guess I’ve nailed it? ;)

function entriesFn(array) {
const out = {};
out[Symbol.iterator] = function* () {
for (let i in array) {
yield [Number(i), array[i]];
}
};
return out;
}

What do you think?

Do you like such a practice tasks?

Appendix

Some other cool (more difficult!) tasks can be found at codility.com

--

--