MST

星途 面试题库

面试题:JavaScript 批量操作 DOM 节点的性能优化

现有一个包含大量 DOM 节点(1000 个以上)的列表,需要对每个节点添加一个点击事件监听器,同时在点击时修改该节点的样式。请从性能角度出发,阐述如何高效地实现这个功能,并且给出代码示例,说明为什么这种方式性能更好。
29.4万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

高效实现方式及理由

  1. 事件委托
    • 理由:如果直接给每个 DOM 节点添加点击事件监听器,会在内存中创建大量的事件处理函数,导致内存开销增大,影响性能。而事件委托利用事件冒泡机制,将事件监听器添加到父元素上。当子元素触发点击事件时,事件会冒泡到父元素,父元素的事件处理函数可以通过判断事件目标来确定是哪个子元素被点击,这样只需要一个事件处理函数,大大减少了内存开销。
  2. 优化样式修改
    • 理由:尽量使用类名来修改样式,而不是直接操作 style 属性。因为直接操作 style 属性会触发重排(reflow)和重绘(repaint),而修改类名,浏览器可以批量处理样式变化,减少重排和重绘的次数,提高性能。

代码示例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
       .clicked {
            background - color: yellow;
        }
    </style>
</head>

<body>
    <ul id="list">
        <!-- 这里假设生成1000个以上的列表项 -->
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
        <!-- 省略更多列表项 -->
    </ul>
    <script>
        const list = document.getElementById('list');
        list.addEventListener('click', function (event) {
            if (event.target.tagName === 'LI') {
                event.target.classList.toggle('clicked');
            }
        });
    </script>
</body>

</html>

在上述代码中,通过事件委托将点击事件监听器添加到 ul 元素上,当点击 li 元素时,判断点击的目标是否为 li,如果是则切换其 clicked 类名,从而修改样式。这种方式减少了事件处理函数的数量,并且通过类名修改样式优化了性能。