为什么 DOM 读/写操作的微小重新排序会导致巨大的性能差异

2024-01-19

下面的代码说明了这个问题,改变读/写的顺序会导致执行时间有很大的差异(使用Chrome、Firefox和IE进行测试):

// read->write->read->write...
function clearSlow(divs){
    Array.prototype.forEach.call(divs, function(div) {
        contents.push(div.clientWidth);
        div.style.width = "10px";
    });
}
// read->read->...->write->write...
function clearFast(divs){
    Array.prototype.forEach.call(divs, function(div) {
        contents.push(div.clientWidth);
    });
    Array.prototype.forEach.call(divs, function(div) {
        div.style.width = "10px";
    });
}

这是完整示例的 JSFiddlehttp://jsfiddle.net/Dq3KZ/2/ http://jsfiddle.net/Dq3KZ/2/ .

我的 n=100 结果:
慢速版本:~35ms
快速版本:~2ms

对于 n=1000:
慢速版本:~2000ms
快速版本:~25ms

我认为这与每种情况下浏览器回流的次数有关。在慢速场景中,每个写操作都会发生回流。然而,在快速场景下,回流仅在最后发生一次。但我不确定也不明白为什么它会这样工作(当操作是独立的时)。

Edit: I used InnerText财产而不是clientWidth and Style.Width,我在使用 Google Chrome 时遇到了相同的行为(http://jsfiddle.net/pindexis/CW2BF/7/ http://jsfiddle.net/pindexis/CW2BF/7/)。然而,当InnerHTML使用时,几乎没有区别(http://jsfiddle.net/pindexis/8E5Yj/ http://jsfiddle.net/pindexis/8E5Yj/).

Edit2:我已经为那些感兴趣的人开启了关于innerHTML/innerText问题的讨论:为什么用innerText替换InnerHTML会导致性能下降>15倍 https://stackoverflow.com/q/19256864/1117720


这些操作不是独立的。

当样式或内容大小发生变化时必须发生重排and需要位置或尺寸,要么是因为您请求尺寸,要么是因为必须更新屏幕(当您的代码完成时)。

div.clientWidth是一个隐藏函数调用。当您请求此值时,您实际上请求的是最新值,因此,随着样式的更改,您会立即触发回流。

在“快速”情况下,在重新绘制屏幕或请求尺寸之前没有理由进行回流。在这种情况下,实际上只需要一次回流焊。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 DOM 读/写操作的微小重新排序会导致巨大的性能差异 的相关文章

  • 为 PostgreSQL 查询选择正确的索引

    简化表 CREATE TABLE products product no integer PRIMARY KEY sales integer status varchar 16 category varchar 16 CREATE INDE
  • Eslint 从另一个文件确定全局变量

    我试图以这样的方式设置 ESLint 使其在对实际目标文件进行 linting 之前解析全局声明文件 这样我就不必将所有确实是全局的函数和变量声明为全局 而是让解析器弄清楚 In 一些 模块 js function do something
  • 如何在 DOM 中的每个元素中调用函数,即使它们是动态创建的

    我想对 DOM 上的特定元素调用函数 例如 red css backgroundColor pink 它适用于 DOM 中已经存在的任何元素 但我也希望在动态添加到 DOM 的元素中调用此方法 我尝试过类似的事情 red on functi
  • 使用 Firefox 插件 sdk 的 nsISocketTransportService

    我正在尝试使用 Firefox 来读取 SSH 横幅 IE 当您最初连接到 SSH 服务器时 服务器会向您发送其横幅 标识服务器软件 并且您向 SSH 服务器发送您的横幅 标识您的客户端软件 为此 我使用以下 URL 中的示例 firefo
  • 在随机位置启动 HTML5

    我有一个大约 2 小时长的音轨 我想在我的网站上使用它 我希望它在页面加载时在随机位置开始播放曲目 使用 HTML5 可以吗 我知道您可以使用 element currentTime 函数来获取当前位置 但是如何在完全下载之前获取曲目的总时
  • 如何在不阻止触摸启动的情况下防止“过度滚动历史导航”?

    我正在实现基于滑动的导航 但我在使用 Chrome 时遇到了麻烦 当页面向右拖动时 会触发新实现的功能 过度滚动历史导航 从而导致跳回 到 历史 1 为了防止这种情况 我必须打电话 preventDefault on touchstart
  • 从 Chrome 扩展中访问响应负载/数据

    我正在开发一个项目 需要跟踪来自某些站点的 ajax 请求 访问其中一些请求的响应负载并对其采取行动 到目前为止 我设法使用以下命令跟踪请求并访问它们的标头网络请求 API http developer chrome com extensi
  • JS 保留以零结尾的小数[重复]

    这个问题在这里已经有答案了 在JavaScript中 是否可以 锁定 十进制数 以保留以零结尾的 浮点数 例如 我有 2 个不同的数字 如下所示 伪代码 let a 1 0 let b 1 00 a b true should be fal
  • React JS 服务器端问题 - 找不到窗口

    你好 我正在尝试在我的reactJS项目中使用react rte 我有服务器端渲染 每次我想使用这个包时 我都会得到 return msie 6 9 b test window navigator userAgent toLowerCase
  • 检查两个数是否是彼此的排列?

    给定两个数字 a b 使得 1 例如 123 是 312 的有效排列 我也不想对数字中的数字进行排序 如果您指的是数字的字符 例如 1927 和 9721 则 至少 有几种方法 如果允许排序 一种方法是简单地sprintf将它们放入两个缓冲
  • 如何在 Web 服务器上设置 gzip 压缩?

    我有一个嵌入式网络服务器 总共有 2 兆空间 通常 您使用 gzip 文件对客户端有利 但这会节省我们在服务器上的空间 我读到你可以只 gzip js 文件并将其保存在服务器上 我在 IIS 上测试过 但没有任何运气 为了使这项工作成功 我
  • 为什么 Delphi 中的 ADO Next 记录处理速度变慢?

    我有一个多年前开发的 Delphi 4 程序 它使用Opus 直接访问 http sourceforge net projects directaccess 按顺序搜索 Microsoft Access 数据库并检索所需的记录 Delphi
  • chrome 扩展弹出窗口和背景 ajax

    我有一个要求 background html 每 10 分钟持续更新一次 当我单击弹出窗口时 它应该触发后台立即更新并在弹出窗口中显示结果 我有使用 ajax 工作的后台更新 并且我有弹出窗口触发后台以使用 ajax 工作进行立即更新 但是
  • 如何使用 window.onerror 捕获所有 javascript 错误? (包括道场)

    这个问题是后续问题javascript 如何在弹出警报中显示脚本错误 https stackoverflow com questions 2604976 javascript how to display script errors in
  • 如何将 Vue.js 作用域样式应用于通过视图路由器加载的组件?

    如何将 Vue js 作用域样式应用于通过以下方式加载的组件
  • ChartJs:如何按时间值(而不是像素)以编程方式平移

    我使用的是chartJs 3 6 1 和 Chartjs plugin zoom 1 2 1 但我认为这并不重要 我有 2 个时间序列折线图 当我通过拖放平移一个图表时 我也想移动 平移另一个图表 为此 我为 graphA 启用了缩放 平移
  • ThreeJS 中阴影的奇怪行为

    所以我有一个 ThreeJS 场景 并且添加了一些球体 多材质 我还添加了定向光 this light new THREE DirectionalLight 0xFFFFFF 1 this light position set 2 10 2
  • Watir Webdriver 加载 Chrome 扩展

    我正在尝试使用 Watir 加载 chrome 扩展 但遇到了问题 我发现这个相关问题 能够启动带有 watir webdriver 加载扩展的 chrome https stackoverflow com questions 125867
  • 如何映射轮播的子项数组?

    我正在尝试将 Carousel 组件包装在映射对象数组周围作为组件的子级 目前我只能让映射创建映射对象的 1 个子对象 轮播需要像这样
  • 如何在 Jquery/Javascript 中绑定模糊和更改,但只触发一次函数?

    我试图在选择元素更改时触发函数 由于 Ipad 在 on change 方面遇到问题 我还想绑定到 blur 这在 Ipad 上工作得很好 但是我不希望两个事件都触发该函数两次 所以我需要某种挂钩来确保两个事件是否都触发change and

随机推荐