本文基于《高性能JavaScript》整理而成。javascript
<script>
标签引用的外部js
文件,仍是内联的<script>
标签,都会阻塞其余浏览器的处理过程,直到js
代码被“下载--解析--执行”完成后,才会继续其余进程。js
文件,但浏览器进程仍然须要等待全部js
文件执行完毕后,才会继续。<script>
标签不会阻塞页面的解析。<body>
前,页面是空白的。<script>
标签放置在页面的底部,仅靠</body>
的上方。此方法能够保证页面在脚本运行前完成解析。将脚本成组打包。css
页面的<script>
标签越少,页面的加载速度越快,响应也更加迅速。不论外部脚本文件仍是内联代码都是如此。为<script>
标签添加defer
属性(只适用于IE
和Firefox 3.5
以上的版本)html
js
代码会在domReady
后执行动态建立<scirpt>
元素,用它下载并执行代码java
<script>
不会阻塞页面的解析,js
代码的处理和页面的解析是并行的用ajax
下载代码,注入页面中ajax
ajax
方式的缺点是不能跨域获取js
代码算法
函数对象编程
建立函数时,会建立一个函数对象,并建立一个做用域链(内部[[scope]]属性
)json
每执行一次函数,就建立一个运行上下文windows
运行上下文也会建立一个做用域链,并将函数对象的做用域链赋值到运行上下文,再新建一个活动对象,置于做用域链的第一个位置。跨域
做用域链:做用域链销毁时,活动对象额一同销毁
with
with
表达式时,运行期上下文的做用域链被临时改变。一个新的可变对象被建立,它包含指定对象的全部属性,此对象被推入做用域链的签到,意味着如今函数的全部局部变量被推入第二个做用域链对象中,全部访问代价更高try catch
catch
块中,会将异常对象推入做用域链签到的一个可变对象中catch
执行完毕,做用域链会返回到原来的状态with
谨慎使用try catch
能够精简代码最小化catch
对性能的影响,一个很好的模式是将错误交给一个专用函数来处理。没有局部变量访问,做用域链临时改变不会影响代码的性能。
背景
优化的JS引擎是经过分析静态代码来肯定哪些变量应该在任意时刻被访问,企图避开传统的做用域链查找,取代以标识符索引的方式进行快速查找。当涉及一个动态做用域后,此优化方法就不起做用了。引发须要切回慢速的寄语哈希表的标识符识别方法,更像传统的做用域链搜索IE
中更被关注,IE使用非本地JS
对象实现DOM
对象,闭包可能致使内存泄露hasOwnProperty()
访问的是实例成员in
访问的是实例+原型成员with
表达式,由于它该变量运行期上下文的做用域链。try-catch
表达式的catch
语句,由于它有一样的效果通常来讲,能够经过如下方法提升性能:
将常常用到的对象成员,数组项和域外变量存入局部变量中,而后,访问局部变量的速度会快于那些原始变量
JavaScript
实现的JavaScript
实现保持相互独立
IE
中
JavaScript
实现:位于库jscript.dll
中DOM
实现:位于另外一个库mshtml.dll(内部代号Trident)
中Safari
中
JavaScript
实现:JavaScriptCore
引擎DOM
实现:Webkit
的WebCore
处理Chrome
中
JavaScript
实现:V8
引擎DOM
实现:Webkit
的WebCore
处理Firefox
中
JavaScript
实现:TraceMonkey
引擎DOM
实现:Gecko
渲染引擎innerHTML
与DOM
方法对比
innerHTML
不是标准的,但被支持的很好DOM
方法有:document.createElement()
等innerHTML
速度更快,除了最新的基于WebKit
的浏览器element.cloneNode()
)
HTML
集合
document.getElementsByTagName()
得到的元素集length
属性,但不是数组length
属性上length
childNodes
nextSibling
IE
中,nextSibling
的效率更高,其余状况下,没太多差异childNodes
、firstChild
、nextSibling
也会返回注释节点和文本节点,所以每次使用都要判断节点类型,比较麻烦children
)
children
替代childNodes
,children
更快,由于集合项更少childElementCount
替代childNodes.length
firstElementChild
替代firstChild
lastElementChild
替代lastChild
nextElementSibling
替代nextSibling
previousElementSibling
替代previousSibling
document.querySelectorAll()
:hover
:hover
for
while
do while
js
中惟一一种后测试的循环,包括:循环体和后测试条件for in
for in
速度最慢,由于它要查找各类属性
优化
若是要迭代一个有限的、已知的属性列表,使用其余循环类型更快,可以使用以下模式(只关注感兴趣的属性):
var props = ["prop1", "prop2"], i = 0; while (i < props.length){ process(object[props[i]]); }
foreach
每次迭代都会调用函数,性能较低if else
switch
switch
。switch
更快if else
if else
组织成一系列嵌套的if else
表达式。使用一个单独的一长串的if else
一般致使运行缓慢,由于每一个条件都要被计算
JavaScript
的运行时间。与其余语言不一样的是,JavaScript
可用资源有限,因此优化技术更为重要for
、while
、do-while
循环的性能特性类似for-in
循环switch
老是比if-else
更快,但并不老是最好的解决办法if-else
或者switch
更快JavaScript
中的应用:栈溢出错误致使其余代码也不能正常执行JavaScript
任务JavaScript
代码运行时用户界面不能对输入产生反应,反之亦然。管理好JS
运行时间对网页应用的性能很重要JS
和UI
更新共享的进程一般被称做浏览器UI线程。JS
代码,就是执行UI更新,包括重绘和排版JS
操做应当使用的总时间(最大)是100毫秒JS
任务由于复杂性缘由不能在100毫秒或更少的时间内完成,这种状况下,理想方法是让出对UI线程的控制,让UI更新能够进行,让出控制意味着中止JS
运行,给UI线程机会进行更新,而后再运行`JSsetTimeout
到达时间后,只是加入队列,并非执行do-while
循环)JavaScript
和用户界面更新在同一个进程内运行,同一时刻只有其中一个能够运行。有效地管理UI线程就是要确保JavaScript
不能运行太长时间,一面影响用户体验。所以要注意:
JavaScript
运行时间不该该超过100毫秒,过长的运行时间致使UI更新出现可察觉的延迟,从而对总体用户体验产生负面影响JavaScript
运行期间,浏览器响应用户交互的行为存在差别,不管如何,JavaScript
长时间运行将致使用户体验混乱和脱节JavaScript
代码而避免锁定UIJavaScript
代码能够重要到容许影响用户体验的程度XMLHttpRequest(XHR)
(经常使用)动态脚本标签插入
(经常使用)Multipart XHR
(经常使用)iframes
(不经常使用)Comet
(不经常使用)XHR
ajax
GET
或POST
GET
GET
GET
请求会被缓存POST
POST
提取数据jsonp
)
GET
方法传递,不能用POST
Multipart XHR
XHR
XHR
主要用于从服务器获取数据,它也能够用来向服务器发送数据GET
和POST
方式发送数据,以及任意数量的HTTP信息头。这样灵活性大。当数据量超过浏览器的最大URL长度时,XHR
特别有用。这时候能够用POST
方式发送数据GET
比POST
快。
GET
请求要占用一个单独的数据包POST
至少要发送两个数据包,一个用于信息头,一个是POST体Image
对象,将src设置为服务器上一个脚本文件的URLImage
对象没必要插入DOM节点POST
数据onload
,不多能获取服务器返回的信息JSON
和字符分隔的自定义格式。数据量大的话,就用这两种格式Ajax
请求
HTTP
头,确保返回报文被缓存在浏览器中Ajax
响应报文,客户端发起请求必须使用GET
方法Expires
头Ajax
包括:知道你项目的具体需求,选择正确的数据格式和与之相配的传输技术XHR
提供最完善的控制和灵活性,尽管它将全部传入数据视为一个字符串,这有可能下降解析速度jsonp
容许跨域,但接口不够安全,并且不能读取信息头或响应报文代码MXHR
能够减小请求的数量,一次响应中处理不一样的文件类型,尽管它不能缓存收到的响应报文XHR
也能够用POST
方法发送大量数据Ajax
的速度
JavaScript
和CSS
打包,或者使用MXHR
Ajax
获取少许重要文件Ajax
库,什么时候编写本身的底层Ajax
代码Ajax
是提高网站性能的最大的改进区域之一JavaScript
容许在程序中获取一个包含代码的字符串而后运行它eval_r()
Function()
构造器setTimeout()
setInterval()
Math
属性
Math.E
Math.LN10
Math.LN2
Math.LOG2E
Math.LOG10E
Math.PI
Math.SQRT1_2
Math.SQRT2
Math
方法
Math.abs(num)
Math.exp(num)
Math.log(num)
Math.pow(num, power)
Math.sqrt(num)
Math.acos(x)
Math.asin(x)
Math.atan(x)
Math.atan2(y, x)
Math.cos(x)
Math.sin(x)
Math.tan(x)
querySelector()
querySelectorAll()
eval_r()
和Function()
构造器避免二次评估,此外,给setTimeout()
和setInterval()
传递函数参数而不是字符串参数JavaScript
写的东西要快。尽可能使用原生方法。JavaScript
文件,减小HTTP
请求的数量JS
文件JS
文件可缓存,经过向文件名附加时间戳解决缓存问题JS
文件,CDN不只能够提升性能,还能够为你管理压缩和缓存