Iterate over set elements
The of
operator doesn't appear to be currently supported in Chrome. It seems that only FireFox versions 13 through 18 support it. It also appears that none of the browsers actually support Set
although the page does say that some of the tests represent existence and not full functionality or coherence. So it might be that Set
is partially implemented in Chrome.
What's the fastest way to loop through an array in JavaScript?
After performing this test with most modern browsers:
https://jsben.ch/wY5fo
Currently, the fastest form of loop (and in my opinion the most syntactically obvious).
A standard for-loop with length caching
var i = 0, len = myArray.length;
while (i < len) {
// your code
i++
}
I would say, this is definitely a case where I applaud JavaScript engine developers. A runtime should be optimized for clarity, not cleverness.
How can I loop through ALL DOM elements on a page?
You can pass a *
to getElementsByTagName()
so that it will return all elements in a page:
var all = document.getElementsByTagName("*");
for (var i=0, max=all.length; i < max; i++) {
// Do something with the element here
}
Note that you could use querySelectorAll()
, if it's available (IE9+, CSS in IE8), to just find elements with a particular class.
if (document.querySelectorAll)
var clsElements = document.querySelectorAll(".mySpeshalClass");
else
// loop through all elements instead
This would certainly speed up matters for modern browsers.
Browsers now support foreach on NodeList. This means you can directly loop the elements instead of writing your own for loop.
document.querySelectorAll('*').forEach(function(node) {
// Do whatever you want with the node object.
});
Performance note - Do your best to scope what you're looking for by using a specific selector. A universal selector can return lots of nodes depending on the complexity of the page. Also, consider using
document.body.querySelectorAll
instead ofdocument.querySelectorAll
when you don’t care about<head>
children.
How do I loop through or enumerate a JavaScript object?
You can use the for-in
loop as shown by others. However, you also have to make sure that the key you get is an actual property of an object, and doesn't come from the prototype.
Here is the snippet:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
for (var key in p) {
if (p.hasOwnProperty(key)) {
console.log(key + " -> " + p[key]);
}
}
Loop through an array by set of 4 elements at a time in Javascript?
Use a for loop where i increases by 4.
Note: I was working on my answer when Jaromanda X commented the same thing.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
for (var i = 0; i < arr.length; i += 4) { console.log("Working with: " + arr.slice(i, i + 4));}
What is the Fastest way of looping over an array on javascript?
Check this JavaScript loop benchmarks.
For loop for HTMLCollection elements
In response to the original question, you are using for/in
incorrectly. In your code, key
is the index. So, to get the value from the pseudo-array, you'd have to do list[key]
and to get the id, you'd do list[key].id
. But, you should not be doing this with for/in
in the first place.
Summary (added in Dec 2018)
Do not ever use for/in
to iterate a nodeList or an HTMLCollection. The reasons to avoid it are described below.
All recent versions of modern browsers (Safari, Firefox, Chrome, Edge) all support for/of
iteration on DOM lists such nodeList
or HTMLCollection
.
Here's an example:
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
To include older browsers (including things like IE), this will work everywhere:
var list = document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
console.log(list[i].id); //second console output
}
Explanation For Why You Should Not Use for/in
for/in
is meant for iterating the properties of an object. That means it will return all iterable properties of an object. While it may appear to work for an array (returning array elements or pseudo-array elements), it can also return other properties of the object that are not what you are expecting from the array-like elements. And, guess what, an HTMLCollection
or nodeList
object can both have other properties that will be returned with a for/in
iteration. I just tried this in Chrome and iterating it the way you were iterating it will retrieve the items in the list (indexes 0, 1, 2, etc...), but also will retrieve the length
and item
properties. The for/in
iteration simply won't work for an HTMLCollection.
See http://jsfiddle.net/jfriend00/FzZ2H/ for why you can't iterate an HTMLCollection with for/in
.
In Firefox, your for/in
iteration would return these items (all the iterable properties of the object):
0
1
2
item
namedItem
@@iterator
length
Hopefully, now you can see why you want to use for (var i = 0; i < list.length; i++)
instead so you just get 0
, 1
and 2
in your iteration.
Evolution of Browser Support for NodeList and HTMLCollection iteration
Following below is an evolution of how browsers have evolved through the time period 2015-2018 giving you additional ways to iterate. None of these are now needed in modern browsers since you can use the options described above.
Update for ES6 in 2015
Added to ES6 is Array.from()
that will convert an array-like structure to an actual array. That allows one to enumerate a list directly like this:
"use strict";
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
console.log(item.id);
});
Working demo (in Firefox, Chrome, and Edge as of April 2016): https://jsfiddle.net/jfriend00/8ar4xn2s/
Update for ES6 in 2016
You can now use the ES6 for/of construct with a NodeList
and an HTMLCollection
by just adding this to your code:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Then, you can do:
var list = document.getElementsByClassName("events");
for (var item of list) {
console.log(item.id);
}
This works in the current version of Chrome, Firefox, and Edge. This works because it attaches the Array iterator to both the NodeList and HTMLCollection prototypes so that when for/of iterates them, it uses the Array iterator to iterate them.
Working demo: http://jsfiddle.net/jfriend00/joy06u4e/.
Second Update for ES6 in Dec 2016
As of Dec 2016, Symbol.iterator
support has been built-in to Chrome v54 and Firefox v50 so the code below works by itself. It is not yet built-in for Edge.
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Working demo (in Chrome and Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
Third Update for ES6 in Dec 2017
As of Dec. 2017, this capability works in Edge 41.16299.15.0 for a nodeList
as in document.querySelectorAll()
, but not an HTMLCollection
as in document.getElementsByClassName()
so you have to manually assign the iterator to use it in Edge for an HTMLCollection
. It is a total mystery why they'd fix one collection type, but not the other. But, you can at least use the result of document.querySelectorAll()
with ES6 for/of
syntax in current versions of Edge now.
I've also updated the above jsFiddle so it tests both HTMLCollection
and nodeList
separately and captures the output in the jsFiddle itself.
Fourth Update for ES6 in Mar 2018
Per mesqueeeb, Symbol.iterator
support has been built-in to Safari too, so you can use for (let item of list)
for either document.getElementsByClassName()
or document.querySelectorAll()
.
Fifth Update for ES6 in Apr 2018
Apparently, support for iterating an HTMLCollection
with for/of
will be coming to Edge 18 in Fall 2018.
Sixth Update for ES6 in Nov 2018
I can confirm that with Microsoft Edge v18 (that is included in the Fall 2018 Windows Update), you can now iterate both an HTMLCollection and a NodeList with for/of in Edge.
So, now all modern browsers contain native support for for/of
iteration of both the HTMLCollection and NodeList objects.
How to iterate over a JavaScript object?
For iterating on keys of Arrays, Strings, or Objects, use for .. in
:
for (let key in yourobject) {
console.log(key, yourobject[key]);
}
With ES6, if you need both keys and values simultaneously, do
for (let [key, value] of Object.entries(yourobject)) {
console.log(key, value);
}
To avoid logging inherited properties, check with hasOwnProperty :
for (let key in yourobject) {
if (yourobject.hasOwnProperty(key)) {
console.log(key, yourobject[key]);
}
}
You don't need to check hasOwnProperty
when iterating on keys if you're using a simple object (for example one you made yourself with {}
).
This MDN documentation explains more generally how to deal with objects and their properties.
If you want to do it "in chunks", the best is to extract the keys in an array. As the order isn't guaranteed, this is the proper way. In modern browsers, you can use
let keys = Object.keys(yourobject);
To be more compatible, you'd better do this :
let keys = [];
for (let key in yourobject) {
if (yourobject.hasOwnProperty(key)) keys.push(key);
}
Then you can iterate on your properties by index: yourobject[keys[i]]
:
for (let i=300; i < keys.length && i < 600; i++) {
console.log(keys[i], yourobject[keys[i]]);
}
Related Topics
Proper Use of Const for Defining Functions
Is Reading the 'Length' Property of an Array Really That Expensive an Operation in JavaScript
How to Intercept All Ajax Requests Made by Different Js Libraries
React Router Doesn't Work in Aws S3 Bucket
Es6: Conditional & Dynamic Import Statements
Safe Evaluation of Arithmetic Expressions in JavaScript
Why Is Immutability So Important (Or Needed) in JavaScript
Add Onclick Event to Newly Added Element in JavaScript
How to Shuffle the Characters in a String in JavaScript
JavaScript Xmlhttprequest Using JSONp
How to Clone a JavaScript Object Except for One Key
Can You Do Desktop Development Using JavaScript
Event Delegation VS Direct Binding When Adding Complex Elements to a Page
How to Set the Prototype of a JavaScript Object That Has Already Been Instantiated