Last active
December 16, 2016 20:28
-
-
Save sammoore/c7fafb0c508ead14eff79fecc13e884b to your computer and use it in GitHub Desktop.
A forEach function with as little assumptions as possible to iterate over classical collections (array-like objects that must be manually iterated, e.g. integer subscripting or through a `.item(i)` function). Akin to Underscore's _.each/forEach for array-like types only, but with a tidbit more control over iteration. Tested with ES5, but theoret…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Iterates over `list`, executing `callback` with each element in the collection. | |
* @requires nothing? | |
* | |
* Designed for array-like objects that are not iterable. | |
* @see https://dom.spec.whatwg.org/#old-style-collections | |
* | |
* Due to some versions of Internet Explorer, if `list.item` is defined, it will be treated as a | |
* function and used rather than integer subscripting. This behavior can be overriden via `useItem`. | |
* @see http://stackoverflow.com/a/10740835 | |
* | |
* @param {Object} list The object with integer indicies, through subscripting or a standard `.item` method, which will be iterated. | |
* @param {Function} callback A callback function to be called for each element up to `len`. | |
* @param {any} thisArg Optional argument which will bind to the callback's `this` value if provided. Use `null` to prevent binding. | |
* @param {Number} len Optional argument stating the length of the enumerable. Defaults to `list.length`. | |
* @param {Boolean} useItem Optional argument stating whether to use `list.item(i)` or integer subscripting. | |
* @throws {TypeError} if `callback` is not a function | |
* @throws {TypeError} if length cannot be coerced via `list.length` or `len` | |
* @returns {undefined} | |
*/ | |
function forEach(list, callback, thisArg, len, useItem) { | |
'use strict'; | |
if (typeof list != 'object' && typeof list != 'array') { | |
throw new TypeError('forEach requires list to be an array or object.'); | |
} | |
if (typeof callback != 'function') { | |
throw new TypeError('forEach requires callback to be a function'); | |
} | |
if (typeof len == 'undefined' && typeof list.length == 'undefined') { | |
throw new TypeError('forEach requires either len or list.length to be defined'); | |
} | |
thisArg = thisArg || null; | |
len = +(len || list.length); | |
var useItem = !!useItem || typeof list.item != 'undefined'; | |
var getter = useItem // for performance, make a getter, rather than checking each time. | |
? function(i) { return list.item(i); } | |
: function(i) { return list[i]; }; | |
var i = 0; | |
while (i < len) { | |
callback.call(thisArg, getter(i)); | |
} | |
return undefined; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NodeList.prototype.forEach = NodeList.prototype.forEach || function(callback, argument) { | |
'use strict'; | |
return forEach(this, callback, argument); | |
}; | |
HTMLCollection.prototype.forEach = HTMLCollection.prototype.forEach || function(callback, argument) { | |
'use strict'; | |
return forEach(this, callback, argument); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment