jQuery to pure JS: Target each direct child of an element

If you’re coming from jQuery to pure Javascript and are trying to target each direct child of an element, your first attempt to select the direct children will probably be element.querySelector('> *'). That will throw an error though, because .querySelector() doesn’t support tag-name wildcards.

Your next attempt might involve element.childNodes, and you’d be closer. The issue with that is that .childNodes will return all of the element’s children, not just the direct children.

The solution we’ll look at does use .childNodes, but there’s a little more to it so it makes sense to write it as a function for reuse.

1const forEachDirectChild = (parent, callback) => {
2 const children = parent.childNodes
4 children.forEach((child, i) => {
5 if (child.nodeType === 1) {
6 return callback()
7 }
8 })

Let’s use the following HTML to illustrate the problem.

1<ul class="list">
2 <li>Direct child of .element</li>
3 <li>Direct child of .element</li>
4 <li>
5 <ul>
6 <li>Not a direct child of .element</li>
7 <li>Not a direct child of .element</li>
8 </ul>
9 </li>
10 <li>Direct child of .element</li>
11 <li>Direct child of .element</li>

I want to target each direct child in the above .list (the 5 lis), so with jQuery would have done as follows.

1$('.list > *').each(() => {
2 // Do something here...

With pure Javascript, thanks to the helper function we just wrote, I can now target each direct child of .list like this:

1forEachDirectChild(document.querySelector('.list'), () => {
2 // Do something here...