如何提升JavaScript的运行速度(DOM篇)[译]
作者:明达 来源:七月佑安 发布时间:2009-02-25 12:24:00
在Web开发中,JavaScript的一个很重要的作用就是对DOM进行操作,可你知道么?对DOM的操作是非常昂贵的,因为这会导致浏览器执行回流操作,而执行了过多的回流操作,你就会发现自己的网站变得越来越慢了,我们应该尽可能的减少DOM操作。本文是这个系列的最后一篇,给出了一些指导性原则,比如在什么时候应该对DOM可以进行什么样的操作等。
【原文】Nicholas C. Zakas - Speed up your JavaScript, Part 4
以下是对原文的翻译:
在过去的几周中,我为大家介绍了几种可以加快JavaScript脚本运行速度的技术。第一节介绍了如何优化循环。第二节的重点放在优化函数内部代码上,还介绍了队列(queuing)和记忆化(memoization)两种技术,来减轻函数的工作负担。第三节就如何将递归转换为迭代循环或者记忆化方式的话题,展开了讨论。第四节是这个系列的最后一篇,也就是本文,将重点阐述过多的DOM操作所带来的影响。
我们都知道,DOM操作的效率是很低的,而且不是一般的慢,而且这也是引发性能问题的常见问题之一。为什么会慢呢?因为对DOM的修改为影响网页的用户界面,重绘页面是一项昂贵的操作。太多的DOM操作会导致一系列的重绘操作,为了确保执行结果的准确性,所有的修改操作是按顺序同步执行的。我们称这个过程叫做回流(reflow),同时这也是最昂贵的浏览器操作之一。回流操作主要会发生在几种情况下:
* 当对DOM节点执行新增或者删除操作时。
* 动态设置一个样式时(比如element.style.width="10px")。
* 当获取一个必须经过计算的尺寸值时,比如访问offsetWidth、clientHeight或者其他需要经过计算的CSS值(在兼容DOM的浏览器中,可以通过getComputedStyle函数获取;在IE中,可以通过currentStyle属性获取)。
解决问题的关键,就是限制通过DOM操作所引发回流的次数。大部分浏览器都不会在JavaScript的执行过程中更新DOM。相应的,这些浏览器将对对DOM的操作放进一个队列,并在JavaScript脚本执行完毕以后按顺序一次执行完毕。也就是说,在JavaScript执行的过程中,用户不能和浏览器进行互动,直到一个回流操作被执行。(失控脚本对话框会触发回流操作,因为他执行了一个中止JavaScript执行的操作,此时会对用户界面进行更新)
如果要减少由于DOM修改带来的回流操作,有两个基本的方法。第一个就是在对当前DOM进行操作之前,尽可能多的做一些准备工作。一个经典的例子就是向document对象中添加很多DOM节点:
/*
for (var i=0; i < items.length; i++){
var item = document.createElement("li");
item.appendChild(document.createTextNode("Option " + i);
list.appendChild(item);
}
*/
这段代码的效率是很低的,因为他在每次循环中都会修改当前DOM结构。为了提高性能,我们需要将这个次数降到最低,对于这个案例来说,最好的办法是建立一个文档碎片(document fragment),作为那些已创建元素元素的临时容器,最后一次将容器的内容直接添加到父节点中:
/*
var fragment = document.createDocumentFragment();
for (var i=0; i < items.length; i++){
var item = document.createElement("li");
item.appendChild(document.createTextNode("Option " + i);
fragment.appendChild(item);
}
list.appendChild(fragment);
*/
经过调整的代码,只会修改一次当前DOM的结构,就在最后一行,而在这之前,我们用文档碎片来保存那些中间结果。因为文档碎片没有任何可见内容,所以这类修改不会触发回流操作。实际上,文档碎片也不能被添加到DOM中,我们需要将它作为参数传给appendChild函数,而实际上添加的不是文档碎片本身,而是它下面的所有子元素。


猜你喜欢
- 一、前言运算符重载:为运算符定义方法所谓重载,就是赋予新的含义同一个运算符可以有不同的功能二、重载作用让自定义的实例像内建对象一样进行运算符
- ThinkPHP提供的视图查询应用功能十分强大,用户利用视图查询功能可以将多个数据表的字段内容按需要进行指定和筛选,组织成一个基于这些数据表
- 01前言数据是数据科学中任何分析的关键,大多数分析中最常用的数据集类型是存储在逗号分隔值(csv)表中的干净数据。然而,由于可移植文档格式(
- 这篇文章主要介绍了Python如何把多个PDF文件合并,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 问题介绍棋盘覆盖问题,是一种编程问题。如何应用分治法求解棋盘覆盖问题呢?分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋
- 1、设置数据库模式为简单模式:打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server-->SQL Se
- create 语句后面的TYPE=MyISAMTYPE=MyISAM 和 ENGINE=MyISAM 都是设置数据库存储引擎的语句 ,(老版
- 如何利用微信JSSDK调用微信扫一扫功能?具体内容如下1. 确保有 调起微信扫一扫接口 权限,测试号可能不行;2. 导入相关JS<sc
- python提供了大量的库,可以非常方便的进行各种操作,现在把python中实现读写csv文件的方法使用程序的方式呈现出来。在编写pytho
- Python计算的位数在电脑上做了一个实验,看看python能计算到多少位,一下是结果。x = math.sqrt((3))print (&
- 如何终止浏览器的 CAHCE 页面?Function Redirect( NewURL ) If&n
- 前言字典为动词“to yield”给出了两个释义:产出和让步。对于 Python 生成器中的 yie
- python turtle自定义画布背景色turtle是python一个简单好用的绘图包,它可以通过设计坐标来实时控制绘图。安装很简单,一行
- 我就废话不多说了,大家还是直接看代码吧~<Form.Item label="作用对象"> &n
- 引言使用python接口来运行caffe程序,主要的原因是python非常容易可视化。所以不推荐大家在命令行下面运行python程序。如果非
- 是不是有这么一个场景,对外提供一堆数据或者是要返回给用户一个结果。但是不想把内部的一些数据和逻辑暴露给对方。。。简单点来说,就是想以服务的方
- Pandas处理CSV文件,分为以下几步:读取Pandas文件统计列值出现的次数筛选特定列值遍历数据行绘制直方图(柱状图)读取Pandas文
- 这篇文章主要介绍了java连接mysql数据库代码实例程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfr
- 如何保持数据库中原有格式不变:这些问题在论坛里面几乎天天有人问~!其实当在输入信息,然后提交信息的时候,所有内容的格式是没有变的。只是在当提