Reimplementing JavaScript Array methods
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
orwhile
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:
- accumulator (accumulates callback’s return value)
- currentValue (current array element value)
- (optional) index (current array index)
- (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 newArray 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