I know I can do this with a simple for loop but I'm trying to understand better how to use forEach
.
What I'm trying to do is, having a list of "a" elements ing from a querySelectorAll(), to obtain an array with the href attributes. What is wrong?
var links = document.querySelectorAll("a");
function get_hrefs(links){
var links_array = links.forEach(function(elem){ return elem.getAttribute("href"); });
return links_array;
}
get_hrefs(links);
I know I can do this with a simple for loop but I'm trying to understand better how to use forEach
.
What I'm trying to do is, having a list of "a" elements ing from a querySelectorAll(), to obtain an array with the href attributes. What is wrong?
var links = document.querySelectorAll("a");
function get_hrefs(links){
var links_array = links.forEach(function(elem){ return elem.getAttribute("href"); });
return links_array;
}
get_hrefs(links);
Share
Improve this question
edited Jul 29, 2015 at 10:11
Vandervals
asked Jul 29, 2015 at 10:02
VandervalsVandervals
6,1048 gold badges53 silver badges101 bronze badges
2
- 3 document.querySelectorAll("a") return a NodeList and not an array – Elheni Mokhles Commented Jul 29, 2015 at 10:05
-
The error in the web console should be giving you some idea what the first problem is. Any documentation on
forEach
should be giving you an idea what the second problem is. – T.J. Crowder Commented Jul 29, 2015 at 10:06
5 Answers
Reset to default 8Use slice
to get an Array, like this:
var links = Array.prototype.slice.call(document.querySelectorAll("a"));
var links_array = links.map(function(elem){ return elem.getAttribute("href"); });
As for the updated question:
var links = document.querySelectorAll("a");
function get_hrefs(links){
links = Array.prototype.slice.call(links);
return links.map(function(elem){ return elem.getAttribute("href"); });;
}
get_hrefs(links);
You're looking for map
rather than forEach
, and you need to call it differently because querySelectorAll
returns a NodeList
, not an arary:
var links = document.querySelectorAll("a");
var links_array = Array.prototype.map.call(links, function(e){
return e.getAttribute("href");
});
That's if you really want the attribute value. If you want the resolved href
, then:
var links = document.querySelectorAll("a");
var links_array = Array.prototype.map.call(links, function(e){
return e.href;
});
Re your updated question, where the function will receive links
and not necessarily know what it is: The code above will work both for true arrays and for array-like things like the NodeList
returned by querySelectorAll
. So no changes needed to handle it.
Just came to this question late — but I believe that this can be achieved in one concise line of code by bining Array.from
and the map()
function:
Array.from(document.querySelectorAll('a')).map(e=>e.href)
If you want to use foreach
, because querySelectorAll
doesn't return array so you can do something like this:
var links = document.querySelectorAll("a");
var links_array = [];
[].forEach.call(
links,
function(elem){
links_array.push(elem.getAttribute("href"));
}
);
var hrefArray = [];
var links = document.querySelectorAll("a");
var Array.prototype.forEach.call(links, function(elem){ hrefArray.push(elem.getAttribute("href")); });
Let forEach
push the elements into an empty array. forEach just iterates over all the elements. What you do with it is your decision.
Other users are pointing to the use of map
. That functions suits the problem well. However the question was to get a better understanding of forEach
.
Cerbrus pointed us to the fact that querySelectorAll
returns a nodelist
. Which I overlook at first. instead of an array. Now a nodelist
is arrayish. So you can still treat it as one by using Array.prototype.forEach.call()
;
Since nodelist
doesn't have the function forEach
we need to invoke it from the Array object. Then we pass a reference to links
using the first argument of call
.