对象 eight war src 查看 javascrip 事件 时间
最近在研读《高性能 JavaScript》,在此做些简单记录。示例代码可在此处查看到。
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
除了这个结果外,同时会显示测试过程中的统计误差,以及相对最好的慢了多少(%),统计误差也是非常重要的指标。
有时候为了得到需要的元素列表,需要组合调用 getElementById 等并遍历返回的节点,但这种繁密的过程效率低下。
使用 CSS 选择器是一种定位节点的便利途径,querySelectorAll 就是 DOM 的原生方法。
- //DOM组合API
- varelements = document.getElementById('menu').getElementsByTagName('a');
- //替换为简便的CSS选择器
- varelements = document.querySelectorAll('#menu a');
在《CSS 动画与 JavaScript 动画》中层提到过页面渲染的一般过程为 JavaScript > 计算样式 > 布局 > 绘制 > 渲染层合并。
Layout(重排) 和 Paint(重绘) 是整个环节中最为耗时的两环,所以我们尽量避免着这两个环节。
当 DOM 的变化影响了元素的几何属性(宽和高)将会发生
(reflow);
- 重排
完成重排后,浏览器会重新绘制受影响的部分到屏幕中,此过程为
(repaint)。
- 重绘
1)重排何时发生
1. 添加或删除可见的 DOM 元素
2. 元素位置改变
3. 元素尺寸改变(包括外边距、内边距、边框宽度、宽、高等属性)
4. 内容改变,例如文本改变或图片被不同尺寸的替换掉。
5. 页面渲染器初始化。
6. 浏览器窗口尺寸改变。
2)批量执行重排
下面代码看上去会重排 3 次,但其实只会重排 1 次,大多数浏览器通过队列化修改和批量显示优化重排版过程。
- //渲染树变化的排队和刷新
- varele = 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)
- varfragment = document.createDocumentFragment();
- varli = document.createElement('li');
- li.innerHTML = 'banana';
- fragment.appendChild(li);
- document.getElementById('fruit').appendChild(fragment);
2.3 将原始元素拷贝到一个脱离文档的节点中(例如 position:absolute),修改副本,完成后再替换原始元素。
1)第一章 加载和执行
将 <script> 标签放到页面底部,也就是 </body> 闭合标签之前。
多种无阻塞下载 JavaScript 的方法:
1. 使用
属性。页面解析到
- defer
事件触发前)。
- onload
2. 动态创建 <script> 元素来下载并执行代码。无论在何时启动下载,文件的下载和执行过程不会阻塞页面其它进程,但返回的代码通常会立刻执行。
3. 使用 XHR 对象下载 JavaScript 代码并注入页面中。优点是下载后不会自动执行,所有主流浏览器都支持,但不能跨域下载。
2)第二章 数据存取
1. 每遇到一个变量,就会经历一次标识符解析的过程,以决定在哪里获取和存储数据。在执行环境的作用域中,标识符所在的位置越深,读写速度也就越慢。因此函数中读写局部变量是最快的,读写全局变量是最慢的。
2. 由于对象成员可能包含其它成员,例如
。每次遇到点操作符,嵌套成员会导致 JavaScript 引擎搜索全部对象成员。对象成员嵌套越深,读取速度越慢。
- window.location.href
就比
- location.href
快。
- window.location.href
3)第五章 字符串与正则表达式
- str = str + "one"; //性能高
- str = "one" + str; //性能差
1. 除 IE 外,浏览器会简单的将第二个字符串拷贝到第一个的后面,如果变量 str 很大的话,就会出现性能损耗(内存占用)就会很高。
2. 正则优化包括:减少分支数量,缩小分支范围;使用非捕获数组;只捕获感兴趣的文本以减少后期处理;使用合适的量词;化繁为简,分解复杂的正则;
4)第六章 快速响应的用户界面
使用定时器让出时间片段,分割大型任务,在文章《JavaScript 定时器分析》中有具体分析。
5)第七章 Ajax
允许客户端只用一个 HTTP 请求就可以从服务器向客户端传送多个资源。
- Mutipart XHR
将资源文件(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 直接量
代码例下:
- varmyObject = {
- name: "pwstrick",
- age: 29
- };
- varmyArr = ["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。
参考资料:
高性能 JavaScript
利用 jsPerf 优化 Web 应用的性能
高性能 JavaScript DOM 编程
读《高性能 javascript》笔记(一)
高性能 JavaScript 重排与重绘
JavaScript 性能优化 DOM 编程
http 响应 对象 eight war src 查看 javascrip 事件 时间
来源: http://www.bubuko.com/infodetail-2081864.html