最近在研读《高性能JavaScript》,在此做些简单记录。示例代码可在此处查看到。

一、DOM

1)DOM和JavaScript

文档对象模型(DOM)是一个独立于语言的,用于操作XML和HTML文档的程序接口(API)。

浏览器通常会把DOM和JavaScript独立实现。例如Chrome中使用Webkit的WebCore库渲染页面,用V8作为JavaScript引擎。

访问DOM天生就慢,将DOM和JavaScript比喻为两个岛屿,两处同行要收过桥费,ECMAScript访问DOM的次数越多,过桥费越贵,因此推荐的做法是尽可能减少过桥的次数。

2)性能测试

下图是对两段代码的性能测试,可在此处查看在线性能测试。

1. 第一段每一次循环都直接用DOM赋值

2. 第二段是先将内容缓存到局部变量中,最后使用一次DOM赋值。

测试结果以每秒钟执行测试代码的次数(Ops/sec)显示,这个数值越大越好。

除了这个结果外,同时会显示测试过程中的统计误差,以及相对最好的慢了多少(%),统计误差也是非常重要的指标。

二、选择器API

有时候为了得到需要的元素列表,需要组合调用getElementById等并遍历返回的节点,但这种繁密的过程效率低下。

使用CSS选择器是一种定位节点的便利途径,querySelectorAll就是DOM的原生方法。

//DOM组合API
var elements = document.getElementById('menu').getElementsByTagName('a');
//替换为简便的CSS选择器
var elements = document.querySelectorAll('#menu a');

上面的例子不能体现效率的区别, 后面又改写了一个。在codepen中书写了一个例子,可以在线查看。

//从列表中选出CSS类是one的节点
var elements = document.querySelectorAll('#menu a.one');var elements = document.getElementById('menu').getElementsByTagName('a'), list=[];
for(var i=0, len=elements.length; i<len; i++) {if(elements[i].className == 'one') {list.push(elements[i]);}
}

三、重绘与重排

在《CSS动画与JavaScript动画》中层提到过页面渲染的一般过程为JavaScript > 计算样式 > 布局 > 绘制 > 渲染层合并。

Layout(重排)和Paint(重绘)是整个环节中最为耗时的两环,所以我们尽量避免着这两个环节。

当DOM的变化影响了元素的几何属性(宽和高)将会发生重排(reflow);

完成重排后,浏览器会重新绘制受影响的部分到屏幕中,此过程为重绘(repaint)。

1)重排何时发生

1. 添加或删除可见的DOM元素

2. 元素位置改变

3. 元素尺寸改变(包括外边距、内边距、边框宽度、宽、高等属性)

4. 内容改变,例如文本改变或图片被不同尺寸的替换掉。

5. 页面渲染器初始化。

6. 浏览器窗口尺寸改变。

2)批量执行重排

下面代码看上去会重排3次,但其实只会重排1次,大多数浏览器通过队列化修改和批量显示优化重排版过程。

//渲染树变化的排队和刷新
var ele = document.getElementById('myDiv');
ele.style.borderLeft = '1px';
ele.style.borderRight = '2px';
ele.style.padding = '5px';

但下列操作将会强迫队列刷新并要求所有计划改变的部分立刻应用:

offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop, scrollLeft, scrollWidth, scrollHeight
clientTop, clientLeft, clientWidth, clientHeight
getComputedStyle() (currentStyle in IE)(在 IE 中此函数称为 currentStyle) 

像offsetHeight属性需要返回最新的布局信息,因此浏览器不得不执行渲染队列中的“待处理变化”并触发重排以返回正确的值。

对于尺寸坐标相关的信息可以参考《JavaScript中尺寸、坐标》。

3)最小化重绘和重排

1. cssText和class

cssText可以一次设置多个CSS属性。class也可以一次性设置,并且更清晰,更易于维护,但有前提条件,就是不依赖于运行逻辑和计算的情况。

// cssText
ele.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
// class
ele.className = 'active';

在《JavaScript特性(attribute)、属性(property)和样式(style)》详细介绍了CSS相关的JS操作。

2. 批量修改DOM

2.1 隐藏元素display:none,应用修改,重新显示display:block

2.2 使用文档片段fragment,在片段上操作节点,再拷贝回文档。

//文档片段(fragment)
var fragment = document.createDocumentFragment();
var li = document.createElement('li');
li.innerHTML = 'banana';
fragment.appendChild(li);
document.getElementById('fruit').appendChild(fragment);

2.3 将原始元素拷贝到一个脱离文档的节点中(例如position:absolute),修改副本,完成后再替换原始元素。

四、其它章节性能介绍

1)第一章 加载和执行

将<script>标签放到页面底部,也就是</body>闭合标签之前。

多种无阻塞下载JavaScript的方法:

1. 使用<script>标签的defer属性。页面解析到<script>标签时开始下载,但并不会执行,直到DOM加载完(onload事件触发前)。

2. 动态创建<script>元素来下载并执行代码。无论在何时启动下载,文件的下载和执行过程不会阻塞页面其它进程,但返回的代码通常会立刻执行。

3. 使用XHR对象下载JavaScript代码并注入页面中。优点是下载后不会自动执行,所有主流浏览器都支持,但不能跨域下载。

2)第二章 数据存取

1. 每遇到一个变量,就会经历一次标识符解析的过程,以决定在哪里获取和存储数据。在执行环境的作用域中,标识符所在的位置越深,读写速度也就越慢。因此函数中读写局部变量是最快的,读写全局变量是最慢的。

2. 由于对象成员可能包含其它成员,例如window.location.href。每次遇到点操作符,嵌套成员会导致JavaScript引擎搜索全部对象成员。对象成员嵌套越深,读取速度越慢location.href就比window.location.href快。

3)第五章 字符串与正则表达式

str = str + "one";//性能高
str = "one" + str;//性能差

1. 除IE外,浏览器会简单的将第二个字符串拷贝到第一个的后面,如果变量str很大的话,就会出现性能损耗(内存占用)就会很高。

2. 正则优化包括:减少分支数量,缩小分支范围;使用非捕获数组;只捕获感兴趣的文本以减少后期处理;使用合适的量词;化繁为简,分解复杂的正则;

4)第六章 快速响应的用户界面

使用定时器让出时间片段,分割大型任务,在文章《JavaScript定时器分析》中有具体分析。

5)第七章 Ajax

Mutipart XHR允许客户端只用一个HTTP请求就可以从服务器向客户端传送多个资源。

将资源文件(CSS、HTML、JavaScript、Base64编码图片)打包成一个由双方约定的字符串分隔符,发送到客户端。

然后用JavaScript代码处理这个字符串,根据“mime-type”类型和传入的头信息解析每个资源。

6)第九章 构建并部署高性能JavaScript应用

1. 合并JavaScript文件以减少HTTP请求数。

2. 压缩JavaScript文件。

3. 在服务器端压缩JavaScript文件(Gzip编码)。

4. 正确设置HTTP响应头来缓存JavaScript文件,通过向文件名增加时间戳避免缓存问题。

5. 使用CDN(Content Delivery Network)提供JavaScript文件。

第八章 编程实践内容比较多,单独令出来作为一节。

五、第八章 编程实践

1)使用Object/Array直接量

代码例下:

var myObject = { name: "pwstrick", age: 29
};
var myArr = ["pwstrick", 29];

2)避免重复工作

也就是惰性模式。减少每次代码执行时的重复性分支判断,通过对对象重定义来屏蔽原对象中的分支判断。

惰性模式分为两种:第一种文件加载后立即执行对象方法来重定义,第二种是当第一次使用方法对象时来重定义。可参考在线demo代码。

在文章《JavaScript设计模式》中有更多的设计模式介绍。

3)位运算

1. 用位运算取代纯数学操作,比如对2取模digit%2可以判断偶数与奇数。

2. 位掩码技术,使用单个数字的每一位来判断选项是否成立。掩码中每个选项的值都是2的幂。例如:

var OPTION_A = 1, OPTION_B = 2, OPTION_C = 4, OPTION_D = 8, OPTION_E = 16;
//用按位或运算创建一个数字来包含多个设置选项
var options = OPTION_A | OPTION_C | OPTION_D;
//接下来可以用按位与操作来判断给定的选项是否可用
//选项A是否在列表中
if(options & OPTION_A) {//...
}

3. 用按位左移(<<)做乘法,用按位右移做除法(>>),例如digit*2可以替换成digit<<2

4)原生方法

无论你的代码如何优化,都比不上JavaScript引擎提供的原生方法快。

1. 数学运算用内置的Math对象中提供的方法。

2. 用原生的CSS选择器查找DOM节点,querySelector或querySelectorAll。

本文转自 咖啡机(K.F.J)   博客园博客,原文链接:http://www.cnblogs.com/strick/p/6769634.html,如需转载请自行联系原作者

JavaScript性能优化 DOM编程相关推荐

  1. javascript性能优化

    2019独角兽企业重金招聘Python工程师标准>>> 很久就想总结一下关于javascript性能优化方面的一些东西,平时也有注意收集这方面的资料.把del.icio.us里的收藏 ...

  2. php5.5参数配置优化,5个PHP性能优化的编程习惯

    在网上搜索了一下编程优化我们都会看到大量的文章,但都是一样的内容,下面我来给各位整理了我觉得最有用的5个PHP性能优化的编程习惯分享给各位,希望文章能给各位带来帮助哦. 1. 不要随便就复制变量 有时 ...

  3. JavaScript性能优化【下】--性能优化的具体方式

    前言 下面出现的代码只做效率测试,若运行,请修改其中存在命名冲突,再进行代码的执行. 代码优化 如何精准测试 JavaScript 性能 本质上就是采集大量的执行样本进行数学统计和分析. 使用基于 B ...

  4. JavaScript 深度剖析 - JavaScript 性能优化

    文章目录 一.性能优化介绍 二.JavaScript 内存管理(Memory Management) 2.1 内存管理介绍 2.2 JavaScript 中的内存管理 三.JavaScript 中的垃 ...

  5. JavaScript性能优化详解

    性能优化介绍 性能优化是不可避免的 无处不在的前端性能优化 function func(){arr = []arr[100000] = 'lg is a dog' } func() JavaScrip ...

  6. JavaScript强化教程——javascript性能优化

    本文为 H5EDU 机构官方 HTML5培训 教程,主要介绍:JavaScript强化教程 --数据存取 数据的存取位置也影响着JavaScript的运行速度,我们来总结一下如能分配存取位置最合理,能 ...

  7. js读取html元素scr,了解一下JavaScript中的DOM编程

    如何在HTML中使用JavaScript 元素 元素用于在HTML页面中嵌入或引入JavaScript脚本代码.该元素默认被定义在 元素中 1.type:该属性定义script元素包含或src引入的脚 ...

  8. DOM性能瓶颈与Javascript性能优化

    这两天比较闲,写了两篇关于JS性能缺陷与解决方案的文章(<JS特性性能缺陷及JIT的解决方案>,<Javascript垃圾回收浅析>),主要描述了untyped,GC带来的问题 ...

  9. JavaScript性能优化:度量、监控与可视化1

    HTTP事务所需要的步骤: 接下来,浏览器与远程Web服务器通过TCP三次握手协商来建立一个TCP/IP连接,类似对讲机的Over(完毕) Roger(明白) TCP/IP模型 TCP即传输控制协议( ...

最新文章

  1. 远哥教你MuleESB系列视频教程
  2. Java将异常入库_Exception异常库
  3. python编程软件例子-python面向对象编程实例
  4. EM 期望最大化算法
  5. python面向对象的三个基本特征 含义和作用简介_面向对象语言的三个基本特征各自特点及优势...
  6. 1031:反向输出一个三位数
  7. 2013 8.20 ip地址的计算总结
  8. 关于VSS上的项目源码管理的注意问题
  9. 鸿蒙os 2.0跑分,预装鸿蒙 OS 2.0!华为 MatePad Pro2 跑分曝光:麒麟 9000、8GB 内存
  10. Linux下vsftpd的安装,Java上传文件实现。
  11. restful levelsHATEOAS
  12. 【模拟信号】基于matlab调相信号产生+解调【含Matlab源码 987期】
  13. [Android Pro] RecyclerView实现瀑布流效果(二)
  14. 公司采购流程管理制度 大小公司通用
  15. 我对“渗透性测试”的理解
  16. Python如何自动播放视频(XXT)
  17. win7添加一个计算机图标,Win7系统任务栏添加计算机图标的步骤图解
  18. 海量数据、丰厚奖金,美团外卖推荐技术评测邀你来战!
  19. 【Android】虚拟环绕声
  20. 免费打造自己的个人网站,免费域名、免费空间、FTP、数据库什么的,一个不能少,没钱,也可以这么任性...

热门文章

  1. 程序员提升编程效率的十五点建议!
  2. 思科分析引擎助力大型数据中心应用发展
  3. 【MongoDB数据库】怎样安装、配置MongoDB
  4. JVM源码分析之FinalReference完全解读
  5. 转发与重定向(forward与redirect)
  6. 深圳.NET俱乐部7月活动小结及照片
  7. ETSI MEC — 网业协同架构
  8. 无处不在的 AWS 云计算
  9. Kubernetes — 容器设计模式
  10. 互联网协议 — ARP 地址解析协议