Add the number of descendants for each li node A web page has a nested list.  The goal is to insert the number of descendants for each li node (except for leaf nodes).

Here is an example of the expected output:

Animals [9]
    Mammals [4]
        Cows
        Donkeys
        Dogs
        Tigers
    Other [3]
        Snakes
        Birds
        Lizards
Fishes [5]
    Aquarium [2]
        Guppy
        Angelfish
    Sea [1]
        Sea trout


Here is the javascript I wrote:

function isLeaf(elem) {
    if(elem.firstElementChild === null) {
        return true;
    }

    else {
        return false;
    }
}

function countDescendants(elem) {
    if(isLeaf(elem)) return 0;

    else {
        let children = elem.firstElementChild.children;
        let count = 0;

        for(let child of children) {
            if(isLeaf(child)) {
                   count++;
            }

            else {
                count = count + 1 + countDescendants(child);
            }

        }
        return count;
    }
}

function insertCount(elem) {
    let count = countDescendants(elem);
    let text = elem.firstChild.textContent.trim();
    text = text + " [" + count + "]";
    elem.firstChild.textContent = text;
}

function traverseDOM(root) {
    let children = root.children;

    for(let child of children) {
        if(!isLeaf(child)) {
            if(child.tagName === "LI") {
                insertCount(child);
            }
            traverseDOM(child);
        }
    }
}

//traverse DOM tree
//try catch is for debugging only
try {
    if(document.body.firstElementChild !== null) {
        traverseDOM(document.body.firstElementChild);
    }
}  catch (err) {
    console.log(err);
}


The code works.  I get this nagging feeling it could be done better.  For example, is there a way to improve the countDescendants function?
I think functional coding style is best suited here, because it will significantly reduce amount of code. Also, you will have clearly separated structure consisting of functions with single responsibility.

Suggested solution

function insertCounts(root) {
    forEachElement(root, (el) =&gt; el.innerHTML = countText(count(el)) + el.innerHTML, el =&gt; !isLeaf(el) &amp;&amp; (el.tagName === 'LI'));
}

function countText(count) {
     return `[${count}]`;
}

function forEachElement(root, apply, predicate = () =&gt; true) {
    Array.from(root.children).forEach(el =&gt; { predicate(el) &amp;&amp; apply(el); forEachElement(el, apply, predicate) });
}

function count(root) {
    return Array.from(root.children).reduce((acc, el) =&gt; isLeaf(el) ? acc + 1 : acc + count(el), 0);
}

function isLeaf(elem) {
    return (elem.firstElementChild === null);
}


try {
    if(document.body.firstElementChild !== null) {
        insertCounts(document.body.firstElementChild);
    }
}  catch (err) {
    console.log(err);
}