Reputation: 4419
I'm reading about querySelector
method, the article suggests that one for example shall use Array.prototype.map.call()
instead of map()
. I have no problem with that, however I don't really see why Array.prototype.map.call()
should be chosen over Array.map()
What makes one better than the other?
let nodes = document.querySelectorAll('div.menu-item')
Array.prototype.map.call(nodes, one => one.innerHTML)
//vs
Array.map(nodes, one => one.innerHTML)
Upvotes: 2
Views: 1464
Reputation: 1074355
What makes one better than the other?
There is no Array.map
in the standard JavaScript library. So if you use it, you're relying on an unspecified feature that may or may not be present in all of your target environments. (Firefox's SpiderMonkey JavaScript engine provides it, for instance; Chrome's V8 engine does not, as of this writing.) So that would be a fairly substantial reason to prefer Array.prototype.map.call
— of those two choices. :-)
But, as ste2425 points out, given your use of let
and arrow functions, you appear to be coding for an ES2015+ environment. In that case (or if you add a polyfill), you can use the mapping features of Array.from
:
let innerHTMLArray = Array.from(nodes, one => one.innerHTML);
Array.from
creates an array from any array-like object or iterable object. The NodeList
from querySelectorAll
is both. :-) And it optionally lets you map the values as it's doing that.
Example:
if (!Array.from) {
console.error("Your browser doesn't support Array.from yet.");
} else {
const htmlArray = Array.from(document.querySelectorAll("div.menu-item"), e => e.innerHTML);
console.log(htmlArray);
}
<div>I'm not included in the result because I don't have the class</div>
<div class="menu-item">Menu item #1</div>
<div class="menu-item">Menu item #2</div>
<div class="menu-item">Menu item #3</div>
Upvotes: 2
Reputation: 6527
First, there is no Array.map
. The use case for the former variant is the following: You won't be able to invoke map
for example via document.querySelectorAll('div')[0].map
. That is to the fact, that document.querySelectorAll
returns a NodeList
and not an array and lacks the map method.
What makes one better than the other?
The question really is not which variant is better. It is about not being able to call map
on the NodeList.
Most functions within the array prototype are able to handle array-like objects as well (that is, objects whose keys are representations of numeric indices) when passed as thisArg
to call(or apply). Hence,
Array.prototype.map.call(array-like, mapFunction)` can map the NodeList just like an array.
There's two alternatives, however:
Array.from(nodes, n => n.innerHTML)
introduced in ES6 and not supported in Internet Explorer. However, when that does not matter, I would prefer this.Array.prototype.slice.call(nodes).map(n => n.innerHTML)
, which works similar (see how does Array.prototype.slice.call() work?) or stick with Array.prototype.map.call
.According to your overall code, however, the usage of (1) seems perfectly fine and I, personaly, would prefer this.
Upvotes: 3