为什么删除元素比添加元素花费更多时间?

Kem*_*eia 19 html javascript performance jquery dom

我有一个有很多行的表(如10.000).
(注意:我意识到有一个很大的表是没有意义的,但我想了解下面的行为).
当我收到新数据时,我想先清除行.奇怪的是,清除表格比从头开始构建行需要更长的时间.使用html("")或普通JS 清除表行innerHTML = ""需要1.5分钟,远远超过构建行本身,这需要不到一秒钟.

所以我的问题是:
- 为什么删除元素比添加它们需要更多时间?"幕后"会发生什么?
(请注意我的问题是为什么一个,我不是在寻找可能的解决方法).

更新:

我注意到表行和单元格已经应用了浮动定义,当我删除浮动时,表格在实例中被清空.
我仍然非常想理解为什么 float会使行的删除速度变慢.
这里有一个小提琴:https://jsfiddle.net/maaikeb/t5pduuue/
在Chrome中,清空表需要25秒,只需23 毫秒即可将其附加到DOM.

*我阅读了以下帖子,但他们更多地讨论了可能的解决方案,而不是为什么删除元素比添加元素需要更多时间,删除它们时实际发生的情况

jQuery空是非常慢
jQuery空的很慢
是什么是用jQuery删除表行的最佳方法?
在javascript jquery中删除表行
- 从非常大的表中删除所有行的最快方法

Dav*_*vid 1

如果您问为什么清空表的时间比追加表的时间长 1000 倍,那么,它不应该这样:这是一个错误。

您可以发现重要的性能差异,具体取决于浏览器、其版本、jQuery 或操作系统的版本,但 25 秒与 23 毫秒太多了。看起来你在某个地方进行了O(N^2)操作。低于这个价格,人们就会开票,浏览器的开发人员也会承认他们。

无论如何,删除元素并不总是比添加元素更快。我们的直觉告诉我们,销毁应该比创建更快,但在操作 DOM 时,情况不一定如此。jQuery 和浏览器都需要做额外的工作来取出元素。

如果您查看jQueryappend()函数的当前 (3.2.1) 实现,您会发现它基本上所做的是使用本机 JS 方法appendChild()。另一方面,jQueryempty()函数html()uses empty())需要循环所有内部元素,并负责删除每个内部元素的相关数据(例如事件)以防止内存泄漏。

而且,如果您只使用普通 JS,浏览器在删除元素时仍然需要检查大量内容。如果你想了解浏览器的内部结构,你可以查看这个Firefox 问题

无论您选择removeChild()innerHtmltextContent(),浏览器总是需要重新计算样式和布局:在 Chromium 中检查这一点

这种错误很常见。如果你在 Chromium 中搜索关键词“removeChild”和“slow”的问题,你会得到一个相当长的列表。有时,它们的出现和消失是由于引入回归的修复,例如在涉及浮动元素的情况下。这另一个对您来说可能特别有趣,因为它证明了一些错误与您选择删除元素的方法无关,并且因为就像您的情况一样,当复杂的 CSS 规则应用于该元素时(建议比浏览器触发了回流)。

我无法在 Firefox 和 Chrome 中重现您的问题,因此我无法解决 25 秒或 1.5 分钟的确切原因,但这似乎确实是更新版本中修复的错误。如果您仍然拥有相同的旧版本并且可以重现它,则值得检查以相反顺序(从 开始lastChild)删除元素是否有帮助。也许您可以避免在删除的浮动兄弟之后重新计算所有浮动兄弟的位置。

下次也许您想开一张票并关注他们如何发现错误并修复它。它将满足您的好奇心,并且您可以了解很多有关浏览器内部原理的知识!