高性能javascript开发

标签(空格分隔): javascript


DOM访问与修改

访问DOM元素是具有代价的,修改元素代价较为昂贵,会导致浏览器重新计算页面的几何变化。

尽量减少DOM访问,做好缓存。

HTML集合&遍历DOM

操作DOM的一个消耗点是遍历DOM,在使用getElementsByTagName(),document.links等时,会收集一个类似数组的集合。这个数组处于一个"实时状态",会自动更新。

<ul id="fruit">
<li>apple</li>
<li>orange</li>
<li>banana</li>
</ul>
<script>
var lis = document.getElementByTagName('li');
var peach = document.createElement('li');
peach.innerHTML = 'peach';
document.getElementById('fruit').appendChild(peach);
console.log(lis.length);//4
//这里获取length会比普通数组获取length时间长很多
</script>

优先使用querySelector()和querySelectorAll()

虽然上面的两个方法不一定就比集合的方法快,但是本身的语法很好,类jquery。支持css选择器。

重绘repaint和重排,回流reflow

浏览器在下载完页面所有组件后,会解析成生成两个内部数据结构----DOM树和渲染树。

DOM树负责表示页面结构渲染树负责表示DOM节点如何显示

DOM树中的每一个显示的节点在渲染树中至少存在一个对应的节点(隐藏的DOM元素display为none在渲染树中没有对应的节点)。

渲染树中的节点被称为“帧”或“盒”,符合css盒模型的定义,理解页面元素为一个具有填充,边距,边框和位置的盒子。一旦DOM树和渲染树构建完成,浏览器就开始显示(绘制)页面元素。

重排:当DOM元素的变化影响了元素的几何属性(高或宽)时,浏览器就需要重新计算元素的几何属性,那么其他的元素的位置和几何属性也会受到影响。浏览器的渲染树部分失效,触发了浏览器重新构造渲染树。

重绘:完成重排后,浏览器会重新绘制受影响的部分到屏幕。

由于浏览器的流布局,对渲染树计算通常只需遍历一次即可。但table及其内部元素除外,它可能需要多次计算才能确定好其在渲染树节点中的属性,通常花费的时间是同等元素的3倍。所以我们不用table元素布局。

发生重排就会发生重绘,但是也可能只发生重绘。

比如我们只对DOM元素操作其背景色,那么就只会发生重绘,不涉及几何元素就不会发生重排。

重绘和重排的代价会有多大?

我们用代码来说明:

var times = 15000;
console.time(1);
for (var i = 0; i < times; i++) {
document.getElementById('div1').innerHTML += 'a';
}
console.timeEnd(1); console.time(2);
var str = '';
for (var i = 0; i < times; i++) {
var tmp = document.getElementById('div2').innerHTML;
str += 'a';
}
document.getElementById('div2').innerHTML = str;
console.timeEnd(2); console.time(3);
var str1 = '';
for (var i = 0; i < times; i++) {
str1 += 'a';
}
document.getElementById('div3').innerHTML = str1;
console.timeEnd(3); 1: 4382.324ms
2: 6.485ms
3: 1.565ms

DOM操作其实不是很可怕,消耗的性能也不是那么大,最重要的重绘和重排。

重排什么时候发生

上面说到重排必然导致重绘,那么那些操作会导致重排?

1、添加或删除可见DOM元素;

2、元素的position位置改变;

3、元素的尺寸改变;

4、内容改变;

5、页面渲染初始化;

6、浏览器窗口尺寸改变;(这个就恶心了,页面说不定会挂掉)

怎么提升性能

浏览器队列

其实浏览器也没有那么傻,它会做很多的工作,一般来说,浏览器会做一个队列,当你要使用这些改变时,它才会去页面中改变。不然,它不会一个一个的去执行这些操作,而是会一起变化,以减小页面的重绘重排。

会刷新队列的操作比如:

1、offsetTop,offsetLeft,offsetWidth,offsetHeight

2、scrollTop,scrollLeft,scrollWidth,scrollHeight

3、clientTop,clientLeft,clientWidth,clientHeight

4、getComputedStyle(),(currentStyle in IE)

cssText

如果真的需要获取样式怎么办,我们使用cssText方法,一次性改变所有的style。

css.style.cssText,在这里需要注意CSSText会覆盖之前的style。或者使用className。

var ele = document.getElementById('div');
ele.style.cssText = ".."//这里重写css
ele.style.cssText += ""//这里添加css ele.className = "active"

fragment文档碎片

使用fragment文档碎片也可以解决这类问题。

脱离动画流

1、使用绝对位置定位页面上的动画元素,将其脱离文档流。

总结

1、尽量不要在布局信息改变时做查询(会导致渲染队列强制刷新)

2、同一个DOM的多个属性改变可以写在一起(减少DOM访问,同时把强制渲染队列刷新的风险降为0)

3、如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排(fragment元素的应用)

4、将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位

参考文献:

1、韩子迟的博客;

高性能javascript的更多相关文章

  1. 《高性能javascript》一书要点和延伸(上)

    前些天收到了HTML5中国送来的<高性能javascript>一书,便打算将其做为假期消遣,顺便也写篇文章记录下书中一些要点. 个人觉得本书很值得中低级别的前端朋友阅读,会有很多意想不到的 ...

  2. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)

    <高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

  3. 《高性能javascript》 领悟随笔之-------DOM编程篇

    <高性能javascript> 领悟随笔之-------DOM编程篇一 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

  4. 各种JS模板引擎对比数据(高性能JavaScript模板引擎)

    最近做了JS模板引擎测试,拿各个JS模板引擎在不同浏览器上去运行同一程序,下面是模板引擎测试数据:通过测试artTemplate.juicer与doT引擎模板整体性能要有绝对优势: js模板引擎 Ja ...

  5. 高性能javascript学习笔记系列(6) -ajax

    参考 高性能javascript javascript高级程序设计 ajax基础  ajax技术的核心是XMLHttpRequest对象(XHR),通过XHR我们就可以实现无需刷新页面就能从服务器端读 ...

  6. 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践

    参考高性能javascript 理解浏览器UI线程  用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程  UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...

  7. 高性能JavaScript 编程实践

    前言 最近在翻<高性能JavaScript>这本书(2010年版 丁琛译),感觉可能是因为浏览器引擎的改进或是其他原因,书中有些原本能提高性能的代码在最新的浏览器中已经失效.但是有些章节的 ...

  8. 高性能javascript学习笔记系列(4) -算法和流程控制

    参考高性能javascript for in 循环  使用它可以遍历对象的属性名,但是每次的操作都会搜索实例或者原型的属性 导致使用for in 进行遍历会产生更多的开销 书中提到不要使用for in ...

  9. 高性能javascript学习笔记系列(3) -DOM编程

    参考 高性能javascript 文档对象模型(DOM)是独立于语言的,用于操作XML和HTML文档的程序接口API,在浏览器中主要通过DOM提供的API与HTML进行交互,浏览器通常会把DOM和ja ...

  10. 高性能javascript学习笔记系列(2)-数据存取

    参考 高性能javascript Tom大叔深入理解javascript系列 相关概念 1.执行上下文   当控制器转到ecmascript可执行代码的时候,就会进入一个执行上下文,执行上下文是以堆栈 ...

随机推荐

  1. C#基础精华04(文件流,文件操作,File、Directory、Path,Directory)

    文件流 FileStream  可读可写  大文件  释放 StreamReader 读取   释放 StreamWriter 写入   释放 using 中释放 File 可读可写  小文件 操作文 ...

  2. MinHash算法-复杂度待整理

    1MinHash简介 传统的hash算法只负责将原始内容尽量均匀随机地映射为一个签名值,原理上相当于伪随机数产生算法.传统hash算法产生的两个签名,如果相等,说明原始内容在一定概率下是相等的:如果不 ...

  3. CentOS7.1 安装VMware Tools

    虚拟机——安装VMware Tools(Install VMware Tools),这时我们会在CentOS7系统桌面上发现VMware Tools的光盘图标. 双击这个图标,会发现VMwareToo ...

  4. Layout Resource官方教程(4)<include>与<merge>

    Re-using Layouts with <include/> THIS LESSON TEACHES YOU TO Create a Re-usable Layout Use the ...

  5. IT项目量化管理:细化、量化与图形化 与 中国IT项目实施困惑

    IT项目开发和实施的组织先后在组织中引入项目管理模型的管理制度.流程和方法,但收入甚微.大量的IT项目依然面临着无休止的需求蔓延与频繁加班.项目工期失控.质量低下等典型的项目失控现象.对项目引入量化意 ...

  6. Android开发之IP拨号器原理

    IP拨号器,使用了Android的广播接收者(BroadCastReceiver),在广播中把已保存的ip号码放在拨打电话号码的前面(getResultData()),然后把修改后的号码设置到广播中( ...

  7. bzoj1196:[Hnoi2010]chorus 合唱队

    这数据范围明显的区间dp啊...然而据说二维会wa...那就写三维把... #include<cstdio> #include<cstring> #include<cct ...

  8. BZOJ3688: 折线统计

    题解: 令f[i][j][0/1]表示前i个数有j段,最后一段是下降/上升的方案数 很容易列出状态转移方程(已按x轴排序) f[i][j][0]=sigma(f[k][j][0]+f[k][j-1][ ...

  9. ,net运行框架

    .NET FrameWork框架 是一套应用程序开发框架,主要目的提供一个开发模型. 主要的两个组件: 公共语言运行时(Common Language Runtime)(CLR): 提供内存管理.线程 ...

  10. ShopNc商城修改详情

    1. 修改400电话.(400.png) a.位置:在页面顶部搜索的后面. b.修改文件: t/layout/home_layout.php 增标签 <img border=0 src=&quo ...