Polyfills In Javascript


Introduction
In this article we will explore the concept of polyfill in JavaScript language. We’ll start with what it is, using a fun analogy. ‘Where to use it?’ and then we will move forward to ‘How to make one yourself with different examples. The concept of polyfills may not be used much nowadays but it does not deny its importance. And back in the days polyfills were very prevalent and were kind of like the walls of dams which if not there, everything will come crashing down. So even if browsers have become quite robust compare to before it is still a concept that can not be overlooked. Knowing this just makes a software engineer make more robust applications. It is also very important concept for interviews.
What are polyfills ?
What are polyfills? to make you understand it I will use my one of my favourite cartoon (not that I expect it’s yours as well). If you ever watched the cartoon of Doraemon you must have seen the gadget named Translation Tool , It is a gadget that enable user to understand any language, even from different space and time. So polyfills are kind of like that, a piece of code defined for a particular functionality which is originally unavailable inside the current browser versions
If you still didn’t get it then do not worry, let’s try professional way. Polyfills in Javascript are piece of code that provide modern functionality to older browsers or environments that do not natively support those features. They allow developers to write code using modern syntax and techniques without waiting for full support across all target browsers.
Where to use it ?
Emulating Web ApIs: For features which are part of the Web Platform APIs but might not be fully implemented in all browsers.
Addressing Browsers-Specific Inconsistencies: In cases where different browsers have implemented same features slightly varying.
Ensuring Broad User Experience: By enabling modern functionalities across a wider range of browsers.
Facilitating Modern Development Workflows: Polyfills allow developers to leverage the latest features and APIs, streamlining development and potentially reducing the need for extensive browser-specific workarounds.
In essence, polyfills are crucial for balancing the adoption of modern web standards with the practical need to support a diverse brower landscape.
How to write polyfill?
Before writing a polyfill of any functionality it is important to know the signature of the feature. In other words it is necessary to note down the characteristics of feature, like what does it do? what arguments or values it takes and how many? how does it evaluate the input. Once we get these answers it becomes somewhat easy to write the logic of the feature. Let us start with some polyfill examples:-
forEach()
forEach is an high order function , which takes a callback that accepts upto 3 arguments (it also takes thisArg , but we won’t discuss it here). It returns undefined and performs a function for each array element.
if(!Array.prototype.forEach){
Array.prototype.forEach = function(callback){
for(let i = 0; i < this.length; i++){
callback(this[i],i,this)
}
return undefined
}
}
Explanation:
!Array.prototype.forEach : checks whether the feature is available. And only implement the polyfill in the absence of the feature, which is good for the better performance of the application.
Array.prototype.forEach = function (callback) : Here a feature named forEach is attached inside the proto of the Array , where a function is declared which takes a callback as a parameter (for now).
for loop : Then we declared a for loop which runs the user’s function for each array element.
return undefined : After closing the for loop, function returns undefined as forEach does not return anything.
This imitates the original forEach exactly to some extent. why at some extent and not fully you asked? …. well this is because we didn’t take thisArg into consideration. Let’s do that now:
if(!Array.prototype.forEach){
Array.prototype.forEach = function(callback,thisArg){
for (let i = 0; i < this.length; i++) {
callback.call(thisArg,this[i],i,this)
}
}
}
The only difference here is thisArg, thisArg refers to this context and to bind it we used call here as In JavaScript, the way to call a function with a custom this
is using callback.call
(thisArg, ...)
.
Hope that till now we get the gist of what a polyfill do. Now practice some more.
map()
Let us think about the signature of map function. It returns a new array after performing function on each element of the array. It takes 2 arguments , a callback which takes upto 3 arguments and another one which is thisArg.
if(!Array.prototype.map){
Array.prototype.map = function(callback,thisArg){
let newArr = []
for(let i = 0; i < this.length; i++){
newArr.push(callback.call(thisArg, this[i], i, this));
}
return newArr
}
}
Explanation:
!Array.prototype.map: checks if the map method is available.
Array.prototype.map = function (callback, thisArg ) : Here a map named feature is attached inside the proto of the Array , where a function is declared which takes a callback as a parameter and thisArg.
thisArg: Here as well thisArg refers to this context and to bind it we used call here as In JavaScript, the way to call a function with a custom this
is using callback.call
(thisArg, ...)
.
let newArr = [] : Declare an empty array here so that later new array can be returned.
for loop : Then we declared a for loop which runs the user’s function for each array element. which also binds the context of this.
newArr.push(callback.call(thisArg, this[i], i, this)) : This line executes the callback for the current element, and its return value is pushed into the new array.
return newArr: Here the function returns new array after loop ends.
This perfectly imitates the functionality of the map feature.
filter()
The signature of filter method is that it returns the current element if the condition is true.
if(!Array.prototype.filter){
Array.prototype.filter = function(callback,thisArg){
let result = []
for (let i = 0; i < this.length; i++) {
if(callback.call(thisArg,this[i], i, this)){
result.push(this[i])
}
}
return result
}
}
!Array.prototype.filter: checks if the map method is available.
Array.prototype.filter= function (callback, thisArg ) : filter named feature is attached inside the proto of the Array , where a function is declared which takes a callback and thisAtg as parameters.
thisArg: We use thisArg again like before.
let result= [] : Declare an empty array here so that later result can be returned.
for loop : Then we declared a for loop which runs the user’s function for each array element. which also binds the context of this.
if(callback.call(thisArg,this[i],i,this)): Checks whether the condition for an element of an array is truthy or falsy.
return result: Here the function returns new array which consist only truthy values after loop ends.
This polyfill also perfectly imitates the functionality of the filter feature.
In essence
Polyfills fill in the missing capabilities, allowing developers to code without the worry of older browser versions and not using modern technologies. Polyfills not only bridge browser gaps but also teach us how built-in methods are designed. Writing polyfills forces you to break down problems into smaller steps — arguments, iteration, return values — which sharpens your fundamentals as a JavaScript developer. Even if you never need to write one in production, understanding polyfills will make you better at debugging, problem-solving, and interviews.
Subscribe to my newsletter
Read articles from Shweta Nigam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
