高性能javascript笔记
----------------------------------------------------------- 第一章 加载和执行 -------------------------------------
1.脚本位置
浏览器在遇到<script>标签时会等待脚本下载完并执行完才会继续渲染页面
因为js代码有可能会改变dom结构,所以需要等待js的执行完成
遇到<script>标签 -> 下载脚本 -> 执行脚本 -> 继续渲染
旧浏览器:逐个下载,逐个执行
新浏览器:并发下载,顺序逐个执行
so: 脚本尽量放在靠近</body>的底部
尽可能合并脚本(下载一个比下载多个快)
2.延迟的脚本
defer:立刻下载,等到onload事件被触发前才执行(仅IE4.0+和Firefox3.5+支持)
动态创建<script>节点:添加到页面时开始下载,下载完成立刻执行
* 下载完成的事件:readystatechange(IE)、onload(其他浏览器)
XHR脚本注入:XMLHttpRequest来获取js文件内容,再动态创建<script>节点
* 必须处于相同域,不适用大型Web应用
3.推荐的方式
先添加动态加载所需的代码,然后加载其他代码:
<script type="text/javascript" src = "loader.js"></script>
<script type="text/javascript">
loadScript("the-rest.js"),function(){
Application.init();
}
</script>
放置</body>闭合标签前,保证DOM结构已经创建完毕,无需其他的时间,例如window.onload来检测页面是否准备好
4.类库
LazyLoad.js:
<script type="text/javascript" src = "lazyload-min.js"></script>
<script type="text/javascript">
LazyLoad.js(["first.js","second.js"]),function(){
Application.init();
}
</script>
lab.js:
<script type="text/javascript" src = "lab.js"></script>
<script type="text/javascript">
$LAB.script("first.js").wait() // 如果需要按序执行则需要加上wait()
.script("second.js")
.wait(function(){
Application.init();
});
</script>
--------------------------------第二章 数据访问---------------------------------------
1.作用域链和标识符解析
内部属性[[Scope]] --- 作用域链 --- 0 --- 活动对象([[Scope]]属性中所包含的对象,即函数范围内的变量)
--- 1 --- 全局对象(this, window, document 等等全局变量)
2.so 尽量把链深处的变量存储到局部变量里,介以提升性能
* 采用优化过的js引擎不存在这种问题,老版的IE、Firefox和Safari都有问题
3.改变作用域链:
with(document){...} //with把document推进了作用域链的第一层,但是导致访问局部变量路径变远了,所以不推荐
try{}catch(ex){} //catch里面把异常对象推入了作用域链的头部
4.访问对象也一样,首先在实例中查找,然后再去原型链中查找
so 如果需要访问多次,那么缓存对象属性可以提升性能
--------------------------------第三章 DOM编程---------------------------------------
1.尽量少访问DOM,把运算留在ECMAScript这一端处理
2.innerHTML属性和类似document.createElement()、document.createTextNode()的原生DOM方法性能差不多
3.cloneNode()比createElement要稍快一点
4.HTML集合
document.getElementsByName();
document.getElementsByClassName();
document.getElementsByTagName();
HTML集合是动态的,类数组,提供一个length属性
* 访问length属性时会重新执行一次查询的过程
so,缓存length属性很有必要
5.只返回元素节点
children childNodes
childElementCount childNodes.length
firstElementChild firstChild
lastElementChild lastChild
nextElementSibling nextSibling
previousElementSibling previousSibling
6.选择器API
原生DOM方法:querySelectorAll();
7.重绘与重排
构建DOM树与渲染树 --- 绘制页面元素
重排:
添加、删除DOM元素
元素位置改变
元素尺寸改变
内容改变(例如文本改变、图片被另外一个不同尺寸的图片替代)
页面渲染器初始化
浏览器窗口尺寸改变
浏览器通过队列化修改并批量执行来优化重排过程,但以下属性会强制刷新队列:
offsetTop, offsetLeft, offsetWidth, offsetHeight
scroll...
client...
getComputedStyle()(currentStyle in IE)
以上属性需要返回最新的布局信息,所以浏览器需要执行队列中的"待处理变化"并触发重排以返回正确的值
so 以上属性尽量少使用,并且使用这些属性的位置应该在修改布局信息的后面,中间的话会导致多次重排
8.最小化重绘和重排
·合并多次所有的改变一次处理
·批量修改DOM
脱离文档流
应用多重改变
带回文档
三种方式:隐藏元素 --- 修改 --- 重新显示
使用文档片段(document fragment)
拷贝 --- 修改拷贝 --- 替换原始(replaceChild(new, old))
9.缓存布局信息
10.让元素脱离动画流
绝对定位页面上的动画元素,将其脱离文档流
让元素动起来,只重绘了该元素,会临时覆盖部分页面
动画结束时恢复定位,只下移一次文档的其他元素
11.元素很多时应避免使用:hover这个CSS伪选择器
12.事件委托
只绑定最外围的元素点击事件,判断来源是否是目标
--------------------------------第四章 算法和流程控制---------------------------------------
1.for-in循环的性能只有其他循环的1/7,
so 尽量不要使用for-in来遍历对象的属性名
2.少量条件用if-else, 大量条件用switch-case
3.列表查找比循环查找要快
so, 数据放置一个Array中, 通过位置来查找
4.尽量减少循环
5.存在重复的计算结果时,可以使用缓存
--------------------------------第五章 字符串和正则表达式---------------------------------------
1.字符串连接
把基础字符串及放置左边可以提升性能
* 因为除IE外,其他浏览器会尝试为左侧的字符串分配更多的内存,然后简单地将第二个字符串拷贝至它的末尾
2.Array.prototype.join();
String.prototype.concat(); //concat比普通的+和+=以及join慢一点
3.正则表达式的编译很快,只需要注意别在循环中重复编译正则表达式就行
while(/regex1/.test(str1))
4.只是检测位置不适用正则表达式
例如检测是否以;结尾:
/;$/ --- str.charAt(str.length-1)== ";";
其他函数有slice、substr、substring、indexOf和lastIndexOf
5.去除首尾空格
用两个子表达式综合效率要高一些,尤其是在处理长字符串时
str.replace(/^\s+/,"").replace(/\s+$/,"");
* 其他有一次性处理完的,但多少有各方面的性能问题
比方说/^\s+|\s+$/,每个字符串都会去匹配这两个分支条件
--------------------------------第六章 快速响应的用户界面---------------------------------------
1.js的执行不应超过100毫秒(用户体验中能忍受的页面阻塞时间最大值)
2.定时器的推荐最小值为25毫秒
* windows系统的最小识别为15毫秒,设置一个小于15毫秒的定时值,IE会锁定
* 在小于10毫秒时,各浏览器各系统均会有不同的表现
3.可以通过定时器来依次执行多个任务
* 将一个任务分割成多个任务,用定时器来执行
4.Web Workers
Worker没有绑定UI线程,适用于纯数据处理,与网页代码通过事件接口进行通信
网页代码:
var worker = new Worker("code.js");
worker.onmessage = faunction(event){
// ...
}
worker.postMessage("Thyiad");
worker代码(code.js):
importScripts("file1.js", "file2.js");
self.onmessage = function(event){
self.postMessage("Hello, " + event.data + "!");
}
--------------------------------第七章 AJAX---------------------------------------
1.常用的三种技术是:XHR、动态脚本注入和multipart XHR
2.XHR
readyState的值
3 正在与服务器交互
4 整个响应已接收完毕,可进行操作
* GET常用来请求数据,POST则用来发送数据
一个GET请求只会发送一次数据包,而一个POST请求会发送两次数据包(一个装载头一个装载正文)
应该在参数接近或超过2048个字符时,才应该使用POST获取数据,因为IE限制URL长度
* 不能跨域请求数据
3.动态脚本注入
动态创建一个script元素,设置src属性为不同域的URL
* 返回的响应消息必须是可执行的JavaScript代码
4.Multipart XHR
一次请求多个资源,从readyState值为3时开始设定一个定时器监听处理数据(需要自己定义数据格式并处理)
* 这种方式资源不会被缓存
* IE6、7不支持readyState为3的状态和data:URL
5.Beancons - 信标
通过创建一个Image,设定src来回传数据
var beacon = new Image();
beacon.src=url+'?'+params.join('&');
beancon.onload = function(){ // 通过监听image的load事件来处理简单返回时间
if(this.width === 1){ // 如果不需要返回数据,那么响应中应该发送一个 204 No Content 状态码(即:不带消息正文)
} // 以阻止客户端继续等待永远不会到来的消息正文
else{}
}
6.数据格式
XML 不推荐,数据量大解析又慢
JSON 推荐,数据轻便解析又快
JSON-P 返回的文本作为js代码直接执行(用eval直接调用)
HTML 不推荐,既缓慢又臃肿
自定义 同JSON,适用的情景下速度还会比JSON更快点
7.缓存数据
用GET请求数据、响应中发送 Expires 头信息:Expires: Mon, 28 Jul 2015 23:30:00 GMT // 告诉浏览器缓存此响应到7月
本地数据存储:使用对象的属性存储缓存(键存url,值存返回数据)
* 本地存储最适用移动设备,大多移动设备的浏览器都很小或没有缓存
--------------------------------第八章 编程实践---------------------------------------
1.避免双重求值
尽量不使用eval和Function构造函数,以避免双重求值带来的性能消耗
同样的,应该给setTimeout()和setInterval()传入函数而不是字符串作为参数
2.使用直接量创建对象和数组 - 效率更高
3.不要重复工作
当需要检测浏览器时,可使用延迟加载或条件预加载
延迟加载:
function addHandler(target, eventType, handler){
if(target.addEventListener){
addHandler = function(target, eventType, handler){
target.addEventListener(eventType, handler, false);
}
}
else{
addHandler = function(target, eventType, handler){
target.attachEvent("on"+eventType, handler);
}
}
addHandler(target, eventType, handler);
}
条件预加载:
var addHandler = document.body.addEventListener ?
function(target, eventType, handler){
target.addEventListener(eventType, handler, false);
} :
function(target, eventType, handler){
target.attachEvent("on"+eventType, handler);
};
4.使用速度快的部分
位操作
toString()方法把数字转换为二进制形式的字符串:
var num = 25;
alert(num.toString(2)); //"11001"
是否为2的整数:
var num = 25;
if(num & 1){ // 奇数&1 => 1
}
else{} // 偶数
位掩码:
var OPTION_A = 1, OPTION_B = 2, OPTION_C = 4, OPTION_D = 8, OPTION_E = 16;
var options = OPTION_A | OPTION_C | OPTION_D;
if(options & OPTION_A){ //选项A是否在列表中
// ...
}
5.原生方法
尽量使用原生方法,比如数学计算(Math)和CSS选择器(querySelector()、querySelectorAll())
--------------------------------第九章 构建并部署高性能JavaScript应用---------------------------------------
1.Apache Ant
2.合并多个JavaScript文件
3.预处理JavaScript文件
在js代码中添加宏定义(#define, #undef)和条件编译(#if, #ifdef, #ifndef)
4.JavaScript压缩
JSMin http://www.crockford.com/javascript/jsmin.html
YUI Compressor http://developer.yahoo.com/yui/compressor
Closure Compiler http://code.google.com/closure/compiler/
Packer http://dean.edwards.name/packer/
5.JavaScript的HTTP压缩
Accept-Encoding HTTP头:值为gzip、compress、deflate和identity
服务器会选择最合适的编码方法,通过Content-Encoding HTTP头来告知浏览器
6.缓存JavaScript文件
* Expires HTTP 响应头
* 客户端存储机制(js自己控制)
* HTML5 离线应用缓存(manifest属性,mime type为text/cache-manifest)
7.处理缓存问题
推荐使用时间戳后缀
8.CDN
--------------------------------第十章 工具---------------------------------------
1.原生分析
new Date(); //通过Date相减
2.YUI Profiler
3.FireBug
4.Console API
profile()、profileEnd()
console.profile("regexTest");
regexTest();
console.profileEnd();
* profileEnd()会阻塞后续执行,所以可以将profileEnd()调用封装在setTimeout中
5.Page Speed
对如何重构进行分析建议,比如哪些脚本在load之前没有用到过,可以延迟加载
* FireBug插件
6.Fiddler
HTTP调试代理工具,整个网络过程的Timeline进行分析,哪块占用时间多需要优化
7.YSlow
分析后的优化建议工具
* FireBug插件
8.dynatrace Ajax Edition
同Fiddler的作用,可以监控整个过程的时间,更能深入到特定的事件
高性能javascript笔记的更多相关文章
- 高性能JavaScript笔记三(编程实践)
避免双重求值 有四个标准函数可以允许你传入代码的字符串,然后它才你动态执行.它们分别是:eval.Function.setTimeout.setInterval 事实上当你在javascript代码中 ...
- 高性能JavaScript笔记二(算法和流程控制、快速响应用户界面、Ajax)
循环 在javaScript中的四种循环中(for.for-in.while.do-while),只有for-in循环比其它几种明显要慢,另外三种速度区别不大 有一点需要注意的是,javascript ...
- 高性能JavaScript笔记一(加载和执行、数据访问、DOM编程)
写在前面 好的书,可能你第一遍并不能领会里面的精魂,当再次细细品评的时候,发现领悟的又是一层新的含义 (这段时间,工作上也不会像从前一样做起来毫不费力,开始有了新的挑战,现在的老大让我既佩服又嫉妒,但 ...
- 关于高性能javascript 笔记
最近买了本新书,准备自己吃 狗粮的同时也吃点精神食粮.笔记总结,从现在开始,看我啥时候能看完这本酥,就酱紫, begin:
- 高性能javascript学习笔记系列(1) -js的加载和执行
这篇笔记的内容主要涉及js的脚本位置,如何加载js脚本和脚本文件执行的问题,按照自己的理解结合高性能JavaScript整理出来的 javascript是解释性代码,解释性代码需要经历转化成计算机指令 ...
- 高性能javascript学习笔记系列(6) -ajax
参考 高性能javascript javascript高级程序设计 ajax基础 ajax技术的核心是XMLHttpRequest对象(XHR),通过XHR我们就可以实现无需刷新页面就能从服务器端读 ...
- 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践
参考高性能javascript 理解浏览器UI线程 用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程 UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...
- 高性能javascript学习笔记系列(4) -算法和流程控制
参考高性能javascript for in 循环 使用它可以遍历对象的属性名,但是每次的操作都会搜索实例或者原型的属性 导致使用for in 进行遍历会产生更多的开销 书中提到不要使用for in ...
- 高性能javascript学习笔记系列(3) -DOM编程
参考 高性能javascript 文档对象模型(DOM)是独立于语言的,用于操作XML和HTML文档的程序接口API,在浏览器中主要通过DOM提供的API与HTML进行交互,浏览器通常会把DOM和ja ...
随机推荐
- Java中的SerialVersionUID
Java中的SerialVersionUID 序列化及SergalVersionUID困扰着许多Java开发人员.我经常会看到这样的问题,什么是SerialVersionUID,如果实现了Serial ...
- [知了堂学习笔记]_Java代码实现MySQL数据库的备份与还原
通常在MySQL数据库的备份和恢复的时候,多是采用在cmd中执行mysql命令来实现. 例如: mysqldump -h127.0.0.1 -uroot -ppass test > d:/tes ...
- javascript学习日志:前言
javascript学习日志系列的所有博客,主要理论依据是<javascript权威指南>(犀牛书第6版)以及<javascript高级程序设计第三版>(红色书),目前js行业 ...
- Spring的RestTemplata使用
spring-web的RestTemplata是对java底层http的封装,使用RestTemplata用户可以不再关注底层的连接建立,并且RestTemplata不仅支持Rest规范,还可以定义返 ...
- C# winform引用com组件,创建AXHOST组件失败解决方案
解决方法非常简单,请首先关闭你的开发工具然后删除所有*.vshost.exe 的文件. 重新打开visual studio开发工具,重新编译你的程序.
- Web Magic设计思想
1.1 设计思想 1. 一个框架,一个领域 一个好的框架必然凝聚了领域知识.WebMagic的设计参考了业界最优秀的爬虫Scrapy,而实现则应用了HttpClient.Jsoup等Java世界最成熟 ...
- MySQL模糊查询中通配符的转义
sql中经常用like进行模糊查询,而模糊查询就要用到百分号“%”,下划线“_”这些通配符,其中“%”匹配任意多个字符,“_”匹配单个字符.如果我们想要模糊查询带有通配符的字符串,如“60%”,“us ...
- SQL SERVER 表最小行的一个纠结问题
昨天一个同事突然问我,说他在SQL 2000数据库创建如下表的时候,突然碰到了下面一条警告信息.SQL脚本和警告信息如下: IF OBJECT_ID(N'Log') IS NULL BEGINCRE ...
- 使用Filebeat和Logstash集中归档日志
方 案 Filebeat->Logstash->Files Filebeat->Redis->Logstash->Files Nxlog(Rsyslog.Logstash ...
- Zabbix3.4部署
Zabbix简介 zabbix(音同 zæbix)是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活 ...