Array.prototype.every

JavaScript polyfill, by , Sunday, March 16th, 2014

The Array.prototype.every() method is not supported in IE8 and older browsers, so if an important share of your visitors use these ancient browsers, and you need to relay on this method, you can use one of the following polyfills.

Array.prototype.every polyfill using a for-loop

This is the most straight forward polyfill for this method, and most likely the one you are looking to use. What it does, is simply iterate over the array on which it is called using a for-loop;

  1. if (!Array.prototype.every) {
  2. Array.prototype.every = function (fn, thisArg) {
  3. "use strict";
  4. var arr = this,
  5. arrLen = arr.length,
  6. i,
  7. T = thisArg ? thisArg : undefined;
  8. for (i = 0; i < arrLen; i += 1) {
  9. if (!fn.call(T, arr[i], i, arr)) {
  10. return false;
  11. }
  12. }
  13. return true;
  14. };
  15. }

Array.prototype.every polyfill using recursion

Another way to write this polyfill is using recursion, which is more of an interesting approach than a practical one, but definitely one to have a look at and think about.

  1. if (!Array.prototype.every) {
  2. Array.prototype.every = function (fn, thisArg) {
  3. "use strict";
  4. var arr = this,
  5. arrLen = arr.length,
  6. T = thisArg ? thisArg : undefined;
  7. return (function ev(i) {
  8. return (!fn.call(T, arr[i], arr)) ? false : (i < arrLen - 1) ? ev(i + 1) : true;
  9. }(0));
  10. };
  11. }

ECMAScript 5.1 compliant version

This version of the polyfill is not one that I would recommend that you use on your live site. Not because it does not work, because it does, but because it is more an illustration of the processes behind the native implementation of the Array.prototype.every() method. So read it in its whole first, and then read the step by step guide that follows, to get a more complete understanding of how this method works;

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

Now lets have a look at the code line by line, following the ECMAScript-262 documentation.

  1. if (!Array.prototype.every) {
  2. Array.prototype.every = function (callbackfn, thisArg) {
  3. "use strict";

The first three lines are not in the documentation, but are necessary for us to successfully make a polyfill. The first line simply checks if the Array.prototype.every() method is available in the current browser or not. If it is not, it declares and initialize the method in line 2, as a function that takes two arguments; callbackfn and thisArg, where callbackfn according to the documentation is;

...[a function that] is called with three arguments: the value of the element, the index of the element, and the object being traversed.

and the thisArg;

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

What this says more precisely is, that the thisArg parameter is optional, and is only used if provided. The third line, in the above code, is forcing the code inside the filter method scope to be executed in strict mode, which is a more clean and safe subset of JavaScript. From now on, we are following the documentation step by step;

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 are making a zero-fill-right-shift, which essentially gives us a 32-bit unsigned integer. This is a hack as there essentially are no integers in JavaScript, but for the sake of illustration, we are allowed to pretend.)

  1. len = lenValue >>> 0,

4. If IsCallable(callbackfn) is false, throw a TypeError exception. (The lines between 6 and 13 are just declaration made at this point because in JavaScript all variable declarations are moved to the top of the current scope, if you do not do this yourself, which can lead to problems.)

  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. (our iterator)

  1. k = 0;

7. Repeat, while k < len

  1. while (k < len) {

7a. Let Pk be ToString(k).

  1. Pk = k.toString();

7b. Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.

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

  1. kValue = O[Pk];

7c ii. Let testResult be the result of calling the [[Call] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.

  1. testResult = callbackfn.call(T, kValue, k, O);

7c iii. If ToBoolean*testResult) is false, return false.

  1. if (!!!testResult) {
  2. return false;
  3. }

7d. Increase k by 1.

  1. k = k + 1;

8. Return true.

  1. return true;

Following each step highlights what is going on, which is basically that on each iteration, if the testResult is false it will return false, else it will return true.