forEach() vs Array.prototype.forEach.call()
javascript
Solution
"class methods" in JavaScript are actually functions defined on a `prototype`. That means that even if an object does not inherit from the `Array` prototype, you can call `Array` methods on it, as long as it follows the array structure (i.e.: It is an object with a `length` property and properties indexed by integers). However, the object holds no reference to `Array.prototype`, so you need to explicitly select `Array.prototype` as the object the method lives in.
The `document.querySelectorAll` function returns a `NodeList`, which is neither an `Array` nor inherits from the `Array` prototype. However, as a `NodeList` has a similar internal structure to an `Array`, you can still use the `forEach` function. But since `NodeList` does not inherit from the `Array` prototype, trying to use `.forEach` on a `NodeList` would raise an error (this is not exactly true - see the note at the end of my answer). For this reason, you need to explicitly state that you are calling a method from `Array.prototype` on the `NodeList`, and that is done by using the `.call` method from `Function.prototype`.
In summary:
Array.prototype.forEach.call(links, function(link) { /* something */ })
means:
Take the `forEach` function from `Array.prototype` and call it on `links`, which is a non-`Array` object, with some function as its argument.
Note that on recent versions of browsers, the `NodeList` prototype does provide a `forEach` method which works the same as the `Array` one, so the example from the Electron API is probably using the `Array` version for compatibility with older versions. If you have a web app and only care about supporting modern versions of Chrome and Firefox, you can just call `forEach` on your `NodeList`. In fact, since Electron updates about 2 weeks after whenever Chrome updates, it should be safe to use `NodeList.prototype.forEach` in Electron. :)
Problem
I was just goin through the Electron API Demo code samples when suddenly a wild expression - which is completely foreign to me - appeared: ``` const links = document.querySelectorAll('a[href]'); Array.prototype.forEach.call(links, function (link) { // WWIII here }) ``` I definitely understand what this piece of code is doing but I am used to a syntax like this: ``` links.forEach(function (links) {}); ``` So what exactly is the difference between those two? I have already read various StackOverflow threads about this topic but they are either ambiguous or don't answer the question at all. Some said it had something todo with array-like collections not being iteratable by .forEach() as opposed to Array.prototype.forEach.call(). Is that the only advantage of the overly tedious and long version? Thanks in advance!