Polyfills

September 12, 2021

banner

Introduction

We all have used arrays multiple times in our lives and with arrays come their methods which facilitate array manipulation. Javascript gives us several array methods and in this blog we will be building them from scratch to learn how they actually work. We will be writing polyfills, wait, polyfill ?

Polyfill

What is a polyfill you might ask: Polyfill is an implementation of a feature, which developers need to do when they are using a feature which might not be supported by all browsers. We will be writing polyfills for map, reduce, filter, forEach, every and some. These methods get used in almost every project and everytime we use an array, so it is crucial for us developers to understand how they actually work.

map()

map() method is used to perform an operation on each element in the array and get a new array of the updated elements. It does not change the elements in the existing array, instead creates a new one and returns it after its execution is complete. The length of the original array and the new array is the same i.e. for every element in the original array there is a corresponding element in the new array.

To create a polyfill for map() we need to:

  1. Accept a callback
  2. Create a new empty array
  3. Iterate over every element in the array (reference of this array is captured in the ‘this’ of the method)
  4. Call the callback on every element and get the value returned by the callback
  5. Push this value to the array created in step 2
  6. Finally, when all elements have been operated on, return the new array
Array.prototype.myMap = function (callback) {
  let result = []
  for (let i = 0; i < this.length; i++) {
    result.push(callback(this[i], i, this))
  }
  return result
}

Testing myMap(): Let’s test and see if the map() provided by the browser and the polyfill that we created return the same values or not.

map myMap

filter()

filter() method is used to perform an operation on each element in the array and get a new array of the elements for which the callback has returned true. It also does not change the elements in the existing array, instead creates a new one and returns it after its execution is complete. The length of the original array and the new array might differ because the new array only contains the elements for which the callback has returned true.

To create a polyfill for filter() we need to:

  1. Accept a callback
  2. Create a new empty array
  3. Iterate over every element in the array (reference of this array is captured in the ‘this’ of the method)
  4. Call the callback on every element and get true/false returned by the callback
  5. Push only those elements for which the callback has returned true, to the array created in step 2
  6. Finally, when all elements have been operated on, return the new array
Array.prototype.myFilter = function (callback) {
  let result = []
  for (let i = 0; i < this.length; i++) {
    if (callback(this[i], i, this)) result.push(this[i])
  }
  return result
}

Testing myFilter(): Let’s test and see if the filter() provided by the browser and the polyfill that we created return the same values or not.

filter myFilter

reduce()

reduce() method is used to perform an operation on each element in the array and get an accumulated value. It also does not change the elements in the existing array but returns a single value which has been accumulated by executing the callback on each element of the array.

To create a polyfill for reduce() we need to:

  1. Accept a callback and an optional ‘initialValue’, this initialValue, if passed, will be the initial value of the accumulator variable
  2. Create a new variable ‘accumulator’ and initialize it to the ‘initialValue’, if passed, otherwise ‘undefined’
  3. Create a new variable ‘idx’ and initialize it to 0
  4. If accumulator holds ‘undefined’ then accumulator will be assigned the element at 0th index in the array and ‘idx’ will be initialized to 1, Note: this simply means that if the user has passed an initialValue for the ‘accumulator’ then we will start the callback function from the 0th index of the array otherwise accumulator will hold the 0th index element from the array and the callback function will start from the 1st index of the array.
  5. Iterate over every element, starting from the index ‘idx’, in the array (reference of this array is captured in the ‘this’ of the method)
  6. Call the callback on every element and get the value returned by the callback
  7. This returned value will be the new accumulator value
  8. Finally, when all elements have been operated on, return the accumulated value
Array.prototype.myReduce = function (callback, initialValue) {
  let accumulator = initialValue ?? undefined
  let idx = 0
  if (accumulator === undefined) {
    accumulator = this[0]
    idx = 1
  }

  for (let i = idx; i < this.length; i++) {
    accumulator = callback(accumulator, this[i], i, this)
  }
  return accumulator
}

Testing myReduce(): Let’s test and see if the reduce() provided by the browser and the polyfill that we created return the same values or not.

reduce myReduce

forEach()

forEach() method is simply a for loop in disguise. It may or may not update the elements of the original array, it depends on whether the callback passed to the forEach method does any array manipulation or not. This method does not return any value.

To create a polyfill for forEach() we need to:

  1. Accept a callback
  2. Iterate over every element in the array (reference of this array is captured in the this of the method)
  3. Call the callback on every element
Array.prototype.myForEach = function (callback) {
  for (let i = 0; i < this.length; i++) {
    callback(this[i], i, this)
  }
}

Testing myForEach(): Let’s test and see if the forEach() provided by the browser and the polyfill that we created return the same values or not.

forEach myForEach

every()

every() method is used to check whether EVERY element in the array satisfies a condition or not. It iterates over every element in the array executing the callback on it, this callback returns true/false on each element.

To create a polyfill for every() we need to:

  1. Accept a callback
  2. Iterate over every element in the array (reference of this array is captured in the ‘this’ of the method)
  3. Call the callback on every element and get the returned true/false
  4. If the callback returns false for any element in the array then, end the execution and return false
  5. If the callback has returned true for every element the return true.
Array.prototype.myEvery = function (callback) {
  for (let i = 0; i < this.length; i++) {
    if (!callback(this[i], i, this)) return false
  }
  return true
}

Testing myEvery(): Let’s test and see if the every() provided by the browser and the polyfill that we created return the same values or not.

every myEvery

some()

some() method is used to check whether ANY element in the array satisfies a condition or not. It iterates over every element in the array executing the callback on it, this callback returns true/false on each element.

To create a polyfill for some() we need to:

  1. Accept a callback
  2. Iterate over every element in the array (reference of this array is captured in the ‘this’ of the method)
  3. Call the callback on every element and get the returned true/false
  4. If the callback returns true for any element then end the execution and return true.
  5. If the callback has returned false for every element in the array then return false
Array.prototype.mySome = function (callback) {
  for (let i = 0; i < this.length; i++) {
    if (callback(this[i], i, this)) return true
  }
  return false
}

Testing mySome(): Let’s test and see if the some() provided by the browser and the polyfill that we created return the same values or not.

some mySome


Copyright © 2022, Vikas Choubey