JavaScript polyfill, by , Saturday, March 22nd, 2014

If you need to execute a function on each element in an array, the Array.prototype.forEach() method is very convenient, but unfortunately not all browsers support it at the time being. If an important part of your audience includes people using IE8 and older, you need a polyfill. I will give you a few to choose from, along with an explanation of each.

forEach polyfill using for-loop

The simplest and most straight forward way of writing a polyfill for the Array.prototype.forEach() method is using a normal for-loop. This way of writing a polyfill is practical and easy to understand, but it leaves out some of the behavior demanded by the specifications. In most cases though, this should be sufficient for your needs.

  1. if (!Array.prototype.forEach) {
  2. Array.prototype.forEach = function (fn, arg) {
  3. var arr = this,
  4. len = arr.length,
  5. thisArg = arg ? arg : undefined,
  6. i;
  7. for (i = 0; i < len; i += 1) {
  8. if (arr.hasOwnProperty(i)) {
  9., arr[i], i, arr);
  10. }
  11. }
  12. return undefined;
  13. };
  14. }

forEach polyfill using recursion

Another approach to writing the polyfill is using recursion. Some people have an apprehension when it comes to recursion, especially in web development, but I do not share that. Most browsers today have such a huge call stack, that you in far the most cases will be just fine. Furthermore, in a future version (ES7) tail recursion will be supported, which means, that you no longer have to worry about stack size, if you write your recursive functions appropriately.

  1. if (!Array.prototype.forEach) {
  2. Array.prototype.forEach = function (fn, arg) {
  3. var arr = this,
  4. len = arr.length,
  5. thisArg = arg ? arg : undefined;
  6. return (function each(i) {
  7. return (i < len) ? (function () {
  8., arr[i], i, arr);
  9. each(i + 1);
  10. }()) : undefined;
  11. }(0));
  12. };
  13. }

ECMAScript 5.1 100% compliant forEach polyfill

If you have an interest in how the actual implementation works, it is always fun to write a polyfill that apply every step in the specifications. So here is a ECMAScript 5.1 100% compliant polyfill for the Array.prototype.forEach() method. Following the polyfill is a step by step explanation.

  1. if (!Array.prototype.forEach) {
  2. Array.prototype.forEach = function (callbackfn, thisArg) {
  3. var O = Object(this),
  4. lenValue = O.length,
  5. len = lenValue >>> 0,
  6. T,
  7. k,
  8. Pk,
  9. kPresent,
  10. kValue;
  12. if (typeof callbackfn !== 'function') {
  13. throw new TypeError();
  14. }
  16. T = thisArg ? thisArg : undefined;
  18. k = 0;
  19. while (k < len) {
  20. Pk = k.toString();
  21. kPresent = O.hasOwnProperty(Pk);
  22. if (kPresent) {
  23. kValue = O[Pk];
  24., kValue, k, O);
  25. }
  26. k += 1;
  27. }
  28. return undefined;
  29. };
  30. }

So lets have a look at the code line by line, following the ECMAScript 5.1 standard step by step.

  1. if (!Array.prototype.forEach) {
  2. Array.prototype.forEach = function (callbackfn, thisArg) {

The first two lines of code are not in the standard, but we need them to first (line 1) check if the method is already available and secondly (line 2), if it is not, declare the method as a function taking two arguments, the first being a callback function and the second being an alternative this value. The callback function is being called as as follows;

callbackfn is called with three arguments: the value of the element, the index of the element, and the object being traversed.

In other words, in your callback you will have the value of the element, the index of the element and the object being iterated available for manipulation or what ever you which to use it for.

The thisArg, is defined as;

If a thisArg parameter is provided, it will be used as the this value for each invocation of the callbackfn. If it is not provided, undefined is used instead.

Besides these two definitions it is important to know, that the forEach method does not directly manipulate or mutate the object being traversed, so if you want to use it to manipulate the array directly, you need to do so in your callback function. With this said, lets follow the specifications step by step; (this definition is taken from the ECMA-262 standard section

1. Let O be the result of calling ToObject passing the this value as argument.

  1. var O = Object(this),

2. Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".

  1. lenValue = O.length,

3.Let len be ToUint32(lenValue). (here we use a trick or hack, depending on how you look at it, to imitate an unsigned integer, as they do not really exist in the language. We are doing it by making a zero-fill-right-shift. You can read more about bitwise operators at Mozillas Developer documentation.)

  1. len = lenValue >>> 0,

The lines from 6 to 10 are just declarations of variables which we are going to use later on. We make them here in the top of the function because all declarations on execution automatically will be moved to the top of the current scope, which again is why it is considered good practice to declare them there from the start.

4. If IsCallable(callbackfn) is false, throw a TypeError exception.

  1. if (typeof callbackfn !== 'function') {
  2. throw new TypeError();
  3. }

5. If thisArg was supplied, let T be thisArg; else let T be undefined.

  1. T = thisArg ? thisArg : undefined;

6. Let k be 0.

  1. k = 0;

7. Repeat, while k < len

  1. while (k < len) {

7a. Let Pk be ToString(k).
7b. Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.

  1. Pk = k.toString();
  2. kPresent = O.hasOwnProperty(Pk);

7c. If kPresent is true, then

  1. if (kPresent) {

7c i. Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
7c ii. Call the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O. (in other words, we are getting the value stored in the array O and storing it in kValue. Then we call the callback function parsing this value along with the index and the array itself.)

  1. kValue = O[Pk];
  2., kValue, k, O);

7d. Increase k by 1.

  1. k += 1;

8. Return undefined.

  1. return undefined;

As you can see, the full implementation is quite cumbersome to write out, but it gives a good insight into how the native implementation works. Of course you could write this more efficiently and get a polyfill that is 100% compliant specifications which is much shorter than given above. For instance, you could build upon the first polyfill shown in this article and write it like this;

  1. if (!Array.prototype.forEach) {
  2. Array.prototype.forEach = function (fn, arg) {
  3. var arr = Object(this),
  4. len = arr.length >>> 0,
  5. thisArg = arg ? arg : undefined,
  6. i;
  7. if (typeof fn !== 'function') {
  8. throw new TypeError();
  9. }
  10. for (i = 0; i < len; i += 1) {
  11. if (arr.hasOwnProperty(i)) {
  12., arr[i], i, arr);
  13. }
  14. }
  15. return undefined;
  16. };
  17. }

This is all a fun exercise, but which one of these you choose to use, is of course up to you, but I would recommend the first one.