forEach() vs Array.prototype.forEach.call()
This is interesting question. Half a year ago I would say that link.forEach
is not about shorter syntax, but it is actually not supposed to work. Then I would explain what it means that many of array methods deliberately generic, which means that their internal implementation only considers numeric indexes and length property of the this
object, but doesn't care about it being Array instance. Basically what @Pedro Castilho said in his answer.
However, now I will say that these days evergreen browsers (except IE11, Edge, as of April 2017) already implemented NodeList.prototype.forEach convenience method so you no longer need to use .call
hack or Array.from
in order to just iterate NodeList with forEach
.
So my summary: if you don't need to support IE, then use NodeList.prototype.forEach
rather than Array.prototype.forEach
. It might be the same internally, but cleaner conceptually. If you do need to support IE and you don't want to include one more pollyfill then use Array.prototype.call
or better Array.from
.
"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. :)