题目

DOM 的体积过大会影响页面性能,假如你想在用户关闭页面时统计(计算并反馈给服务器)当前页面元素节点的数量总和、元素节点的最大嵌套深度以及最大子元素个数,请用 JS 配合原生 DOM API 实现需求(不用考虑陈旧浏览器以及在现代浏览器中的兼容性,可以使用任意浏览器的最新特性;不用考虑 shadow DOM)。比如在如下页面中运行后:

<html>
    <head></head>
    <body>
        <div>
            <span>f</span>
            <span>o</span>
            <span>o</span>
        </div>
    </body>
</html>

会输出:

{
    totalElementsCount: 7,
    maxDOMTreeDepth: 4,
    maxChildrenCount: 3
}

编程实现(可以查阅相关 DOM API,但是不可以使用前端框架 or 类库):

export function calculateDOMNodes () {
    // your implementation code here:
}
window.addEventListener('close', calculateDOMNodes);

回答记录

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

    <div>
        <div>
            <div></div>
        </div>
        <div></div>
    </div>
    <div>
        <div></div>
    </div>
<script>


let counts;

window.addEventListener('beforeunload', () => {
    counts = walk(document.body);
    navigator.sendBeacon('http://127.0.0.1:10000/beacon', JSON.stringify(counts));
});

window.addEventListener('close', calculateDOMNodes);

function calculateDOMNodes () {
    navigator.sendBeacon('http://127.0.0.1:10000/beacon', JSON.stringify(counts));
}

console.log(walk(document.body));

function walk (root) {

    let start = Date.now();

    let stack = [root];
    let nextLevel = [];
    
    let totalElementsCount = -1;
    let maxDOMTreeDepth = 0;
    let maxChildrenCount = 0;

    while (stack.length || nextLevel.length) {
        if (!stack.length) {
            stack = nextLevel;
            nextLevel = [];
            maxDOMTreeDepth++;
            continue;
        }
        let ele = stack.pop();
        totalElementsCount++;
        if (maxChildrenCount < ele.children.length) maxChildrenCount = ele.children.length;
        nextLevel.push(...ele.children);
    }

    return {
        totalElementsCount,
        maxDOMTreeDepth,
        maxChildrenCount,
        time: Date.now() - start
    };
}
</script>
</body>
</html>

1059802125
19 声望3 粉丝