如何使用 document.querySelectorAll 遍历选定的元素

我正在尝试对使用 document.querySelectorAll 查询的选定元素进行循环,但是如何进行呢?

例如,我使用:

var checkboxes = document.querySelectorAll('.check');
for( i in checkboxes) {
console.log(checkboxes[i]);
}

产出:

<input id="check-1" class="check" type="checkbox" name="check">
<input id="check-2" class="check" type="checkbox" name="check">
<input id="check-3" class="check" type="checkbox" name="check">
<input id="check-4" class="check" type="checkbox" name="check">
<input id="check-5" class="check" type="checkbox" name="check">
<input id="check-6" class="check" type="checkbox" name="check">
<input id="check-7" class="check" type="checkbox" name="check">
<input id="check-8" class="check" type="checkbox" name="check">
<input id="check-9" class="check" type="checkbox" name="check">
<input id="check-10" class="check" type="checkbox" name="check" checked="">


10
item()
namedItem()

我的问题是在最后这个方法返回3个额外的项目。我怎样才能正确地做到这一点?

118229 次浏览

for in loop is not recommended for arrays and array-like objects - you see why. There can be more than just number-indexed items, for example the length property or some methods, but for in will loop through all of them. Use either

for (var i = 0, len = checkboxes.length; i < len; i++) {
//work with checkboxes[i]
}

or

for (var i = 0, element; element = checkboxes[i]; i++) {
//work with element
}

The second way can't be used if some elements in array can be falsy (not your case), but can be more readable because you don't need to use [] notation everywhere.

A nice alternative is:

[].forEach.call(
document.querySelectorAll('.check'),
function (el) {
console.log(el);
}
);

but as pointed out, you should use a for loop.

My favorite is using spread syntax to convert the NodeList to an array and then use forEach for looping.

var div_list = document.querySelectorAll('div'); // returns NodeList
var div_array = [...div_list]; // converts NodeList to Array
div_array.forEach(div => {


// do something awesome with each div


});

I code in ES2015 and use Babel.js, so there shouldn't be a browser support issue.

With ES6, there is a static method Array.from to take advantages of Array non-static methods (map, filter, ...) :

Array.from(document.querySelectorAll('div')).forEach((element,index) =>
{


// handle "element"


});

Another use of Array.from since querySelector provides item method:

var all = document.querySelectorAll('div');
// create range [0,1,2,....,all.length-1]
Array.from({length: all.length}, (v, k) => k).forEach((index) => {
let element = all.item(index);
});

It looks like Firefox 50+, Chrome 51+ and Safari 10+ now all support the .forEach function for NodeList objects. Note—.forEach is not supported in Internet Explorer, so consider one of the approaches above or use a polyfill if IE support is required.

https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach

const paragraphs = document.querySelectorAll('p');
paragraphs.forEach(p => console.log(p));
<p>paragraph 1</p>
<p>paragraph 2</p>
<p>paragraph 3</p>
<p>paragraph 4</p>
<p>paragraph 5</p>

A Main Takeaway:

The type matters.

.map will not work directly on a NodeList but will on an Array.

Compare these: Array.prototype.map() NodeList.forEach()

Options:

ES6 available?

  1. The spread operator [...element_list] then Array.map()
  2. Array.from() on a NodeList.forEach()

ES6 NOT available?

  1. NodeList.forEach()
  2. A "for loop"

The shortest and cleanest way to be able to use any regular Array methods, or in your case a for in loop on a NodeList, is to spread it into an array as you fetch it:

const checkboxes = [...document.querySelectorAll('.check')];


for (i in checkboxes) {
console.log(checkboxes[i]);
}

U can select all elements using querySelectorAll method. It will return an array of nodeList.

Lets say u want to select all p tags

<p>paragraph 1</p>
<p>paragraph 2</p>
<p>paragraph 3</p>
<p>paragraph 4</p>
<p>paragraph 5</p>
const paragraphs = document.querySelectorAll('p');

Now the paragraphs has a forEach method which can be used to loop through the nodelist

paragraphs.forEach(console.log); (logs node)

For me the most clean and accessible is for of syntax. The second options for me is the spread operator (...) if ES6 is available. Finally, forEach if you are building big app and you want to provide support for most of the browsers out there.

const lis = document.querySelectorAll('li')


let results = {
'for': [],
'forEach': [],
'three-dots': [],
}


// ES6 bellow
for (const li of lis) {
results['for'].push(li)
}


// ES6 above
[...lis].forEach((li) => results['three-dots'].push(li))


// Most browsers support it
lis.forEach(li => results['forEach'].push(li))


console.log({results})
<u>
<li>Item 01</li>
<li>Item 02</li>
<li>Item 03</li>
<li>Item 04</li>
<li>Item 05</li>
<li>Item 06</li>
<li>Item 07</li>
<li>Item 08</li>
</u>

// for class
for (const elem of document.querySelectorAll('[class=".check"]')){
//work as per usual
};


// for name
for (const elem of document.querySelectorAll('[name="check"]')){
//work as per usual
};


// for id
for (const elem of document.querySelectorAll('[id="check-1"]')){
//work as per usual
};

This provides me with flexibility on what element I would like to work with.