DEV Community

webit
webit

Posted on

Reimplementing JavaScript Array methods

This is cross-post from medium, where I published it first.

Array.filter() implementation

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.

The task

Task #6 —Array methods
since 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 also got 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){}
Enter fullscreen mode Exit fullscreen mode

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.
MDN

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;
}
Enter fullscreen mode Exit fullscreen mode

Array.filter()

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

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;
}
Enter fullscreen mode Exit fullscreen mode

Array.reduce()

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

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 accepts 4 parameters:

  1. accumulator (accumulates callback’s return value)
  2. currentValue (current array element value)
  3. index (current array index)
  4. array (complete entry array)

Additionally in case reducer has no initial value we need to take 1st array item as it!

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;
}
Enter fullscreen mode Exit fullscreen mode

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.
MDN

It is similar function to previous one but it starts executing callback function from the right (from the end). Iterates from 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.

Again, initial value might be omitted so we need to take array item as it. In case reduceRight() it's a last item of array!

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;
}
Enter fullscreen mode Exit fullscreen mode

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.
MDN

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;
}
Enter fullscreen mode Exit fullscreen mode

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.
MDN

As you can see Array.some() is similar to Array.every() the difference is subtle — we got true 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;
}
Enter fullscreen mode Exit fullscreen mode

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.
MDN

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 [+i, array[i]];
    }
  };
  return out;
}

Enter fullscreen mode Exit fullscreen mode

What do you think?

Do you like such a practice tasks?

Latest comments (1)

Collapse
 
eneskaplan profile image
Enes Kaplan

This was a good read, thanks for the write up.

We use these functions daily but trying to implement them is a good exercise to gain more insight. Most of these are fairly straightforward and I think you did a great job covering them, however I think Array.entries() could use a bit more explanation. Haven't seen function*, yield and Symbol.iterator syntax before, could you maybe elaborate a bit for me?