Back in the days of IE6 and Netscape, each browser had its own way of interpreting JavaScript. This inconsistency often broke websites across platforms. To bridge this gap, developers introduced a clever solution: polyfills.
A polyfill sometimes referred to as a Polyfiller, is a piece of code (usually JavaScript on the Web) used to provide modern functionality on older browsers that do not natively support it.
The term “polyfill” is a combination of “poly,” meaning many, and “fill,” indicating filling in the gaps.
Polyfills are used to bring new or standardized features to older browsers or environments that do not inherently support those features.
When new JavaScript features were introduced or when web standards evolve, not all browsers immediately implement those changes. This can create a sticky situation for developers where they want to use latest language features or APIs but still need to support older browsers. In such cases, they can include polyfills to ensure that the required functionality is available across a broader range of browsers.
Polyfills usually have two basic components: feature detection and feature implementation.
1 . Feature Detection
First, you have to check the need or it is required means to check whether the functionality of polyfill is already implemented, if it is then you don’t need to implement further just stops there. Otherwise, if the browser actually is missing the feature, you can proceed to the next step. It is similar to conditional support check.
This step is omitted in overriding polyfills where you override any existing behavior and instead use your implementation
This approach guarantees that every browser will behave the way you expect, but it has the disadvantage of causing potentially unnecessary overhead from overriding the native implementation of a feature.
2 . Feature Implementation
This is the meat of the polyfill where you actually implement the missing feature.
Polyfills Examples: Adding Prototype Methods
In ECMAScript 5, there were many new Array prototype methods added that emphasized a functional programming approach to manipulating arrays. An example of this is filter
method.
Its signature involves accepting a user-defined callback function. The filter
method does not modify the original array; instead, it returns a new array containing only the elements from the original array for which the callback function evaluates to true
.
For example, you could filter an array to only contain even values.
const anotherArr = [1, 2, 3, 4, 5, 6]
if (!Array.prototype.myFilter) {
Array.prototype.myFilter = function (userFn) {
const result = [];
for (let i = 0; i < this.length; i++) {
if (userFn(this[i])) {
result.push(this[i]);
}
}
return result;
}
}
console.log("myfilter", anotherArr.myFilter((e) => e % 2 == 0));
console.log("original Array",anotherArr);
Expected Output:
myfilter [ 2, 4, 6 ]
original Array [ 1, 2, 3, 4, 5, 6 ]
Visualization of the code
The filter
method has an optional second parameter to bind to the this
value of the function. For example, you could bind an object as this
to the function passed to filter
.
let fruits = {
banana: "yellow",
strawberry: "red",
pumpkin: "orange",
apple: "red"
};
let isRedFruit = function(name) {
return this[name] === "red";
};
["pumpkin", "strawberry", "apple", "banana", "strawberry"].filter(isRedFruit, fruits);
Expected Output:
[ 'strawberry', 'apple', 'strawberry' ]
Since this was a feature added in ES5, older browsers, such as Internet Explorer 8 and below, do not support the filter
method.
Example: Second Method (push)
Another light but vital array method among Array prototype methods, is push
.
As it’s signature returns new length of array and adds value at the end. While it add value at the end of an array but it does not creates a new array like native push
.
// Signature of push - returns new length of array and adds value at the end
if (!Array.prototype.mypush) {
Array.prototype.mypush = function () {
let length = this.length; // Get the current array length
// Loop through all arguments passed to mypush
for (let i = 0; i < arguments.length; i++) {
this[length] = arguments[i]; // Add each argument to the end of the array
length++; // Increase the length counter
}
return length; // Return the updated length of the array
}
}
console.log("mypush", anotherArr.mypush(7, 8, 9));
console.log("original array", anotherArr);
Expected Output:
mypush 9
original array [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
We are getting the length of current array through this.length
and storing it in a variable(which is length
)
This is optional we can also do like this; in a more optimized way
if (!Array.prototype.mypush) {
Array.prototype.mypush = function () {
for (let i = 0; i < arguments.length; i++) {
this[this.length] = arguments[i]; // Directly use this.length
}
return this.length; // Return the updated array length
};
}
Expected Output:
mypush 9
original array [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Example: Third Method (map)
The map()
method was introduced in ECMAScript 5 (ES5), released in 2009 with an intriguing functionality.
The map()
method in JavaScript is used to transform each element of an array by applying a callback function, returning a new array without modifying the original one.
It takes a callback with up to three parameters: the current element, its index, and the original array.
For each element, map()
executes the callback, collects the results, and returns an array of the same length.
For example:
if (!Array.prototype.mypush) {
Array.prototype.mypush = function () {
for (let i = 0; i < arguments.length; i++) {
this[this.length] = arguments[i];
}
return this.length;
};
}
if (!Array.prototype.myMap) {
Array.prototype.myMap = function (userFn) {
const result = [];
for (let i = 0; i < this.length; i++) {
const value = userFn(this[i], i);
result.mypush(value)
}
return result;
}
};
console.log("mymap", anotherArr.myMap((v) => v * 2));
console.log("original array", anotherArr)
Expected Output:
mymap [ 2, 4, 6, 8, 10, 12, 14, 16, 18 ]
original array [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
In this example, if mypush
method in prototype of Array prototype methods is undefined, and if so defines it by creating a function mypush
which iterates over every argument passed to mypush
and add each argument to the end of the array while at the same time update the length of the array.
Likewise, mymap
function method creates a new array, applies a user-defined callback function (userFn
) to each array element, and pushes the results into the new array using result.mypush(value)
.
Finally, it returns the transformed array without keeping the original one intact.
The map()
method is supported by all modern browsers, including Chrome, Firefox, Safari, Edge, and Opera.
However, it is not supported in Internet Explorer 8 and earlier versions.
More Resources »
polyfill (article by Remy Sharp, the originator of the term)
Read More Blogs of mine
Conclusion
A Polyfill, or Polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. They are used to provide modern features and changes that Some obsolete browser does not supports.