高性能javascript学习笔记
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
高性能javascript学习笔记
一、加载和执行
<script>标签每次出现都让页面等待脚本的解析和执行,无论当前javascript代码是内嵌的还是包含在外链文件中的,都必须停下来等待脚本执行完成之后才继续页面的下载和渲染,用户的交互。
因为当遇到<script>标签时,HTML页面无法获知javascript代码会不会该改变页面的内容,因此页面会停止下载和渲染,等待执行完javascript代码之后才继续。
1、脚本位置
浏览器在解析到<body>之前不会渲染页面的任何部分,js文件下载之后还有一段延时用于执行,在不能并行下载的浏览器中很耗时,IE8,Firefox3.5,Safari4和Chrome2允许并行下载javascript文件,但是仍然会阻塞其他资源下载和页面渲染。
因此尽可能的将的<script>标签放到<body>标签的底部,减少对整个页面下载的影响。
2、组织脚本
每个<script>标签初始下载时都会阻塞页面渲染,应该减少页面包含的<script>标签数,包括内嵌脚本和外链脚本。
内嵌脚本放在外链样式<link>标签之后,内嵌脚本为了在执行时获得最精确的样式信息,会阻塞页面渲染而去等待样式表的下载,因此不要把内嵌脚本紧跟在<link>标签之后。
外链脚本:HTTP请求会带来额外的性能开销,因此下载单个100KB的文件比下载4个25KB的文件快,减少页面中外链脚本文件的数量有助于改善性能。
大型网站依赖多个javascript脚本文件,我们可以将多个javascript文件合并为一个文件,只引用一个<script>标签,减少性能消耗。
文件合并工作可以通过离线打包工具或者类似Yahoo!combo handler的实时在线服务实现。
雅虎提供了合并处理器。
通过使用指定文件(一个或多个)合并处理后的URL来获取任意数量的YUI文件。
3、无阻塞的脚本
减少javascript文件大小并限制HTTP请求数只是优化web的第一步,下载单个的较大的javascript文件只请求一个HTTP,但是会锁死浏览器一大段时间,阻塞页面。
所以需要向页面中逐步加载javascript文件,这样某种程度上不会阻塞浏览器。
无阻塞的秘诀:在页面加载完成后才加载javascript代码,就是window对象的load事件触发之后再下载脚本。
1)延迟的脚本
HTML4为<script>标签定义了一个扩展属性:defer。
该属性只在IE4和Firefox3.5的浏览器中支持,在其他浏览器,defer会被直接忽视。
defer属性指明本元素所含的脚本不会修改DOM,代码可以安全的延迟执行。
使用:
外链:<script type = "text/javascript" src = "file.js" defer></script>
内嵌:
<script defer>
alert(defer)
</script>
任何带defer属性的<script>元素在DOM完成加载之前都不会执行,无论是内嵌还是外链。
可以放在文档的任何位置,对应的javascript文件在页面解析到<script>标签时才开始下载,但是不会执行,直到DOM加载完成(onload事件被触发之前)。
带有defer属性的javascript文件下载时不会阻塞浏览器其他的进程,它可以和页面中的其它资源并行下载。
若是目标浏览器只是IE和Firefox3.5,可以很好的延迟,但若是兼容其他则不可取。
2)动态脚本元素
使用DOM动态的创建script标签:
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "file.js";
document.getElementByTagName("head")[0].appendChild(script);
技术重点:无论何时开始下载,文件的下载和执行都不会阻塞页面其他元素的进程,甚至可以将代码放到<head>区域也不会影响页面其他部分。
将新创建的<script>标签添加到<head>标签中比添加到<body>中保险。
该元素在被添加到页面时下载,下载动态脚本文件返回的代码,会被立刻执行(除了Firefox 和Opera会等待此前所有的动态脚本节点执行完毕,之后才执行)。
将script加入head之后我们不能马上调用其中的js。
因为浏览器是异步加载这个js文件的,我们不知道他什么时候加载完,非IE浏览器会在<script>元素接收完成时触发一个loadhi见,因此可以监听此事件来获得脚本加载完成时的状态。
IE支持另外一种实现方式,它会触发一个readystatechange事件,<script>元素提供一个readyState属性,它的值在外链文件下载的过程的不同阶段会发生变化,有五种值:
“uninitialized”初始状态
“loading”开始下载
“loaded”下载完成
“interactive”数据完成下载但尚不可用
“complete”所有数据已准备就绪
兼容标准和IE的方法:
callback()是完成接js文件加载后的回调函数
function loadScript(url,callback){
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
//IE
if(script.readyState){
script.onreadystatechange = function () {
if (this.readyState == 'complete' || script.readyState == "loaded") { script.onreadystatechange = null;
callback();
}
};
}else{//其他浏览器
script.onload= function(){
callback();
};
}
script.src = "url";
head.appendChild(script);
}
3)XMLHttpRequest脚本注入
使用XMLHttpRequest对象获取脚本并注入页面。
首先创建一个XMLHttpRequest对象,然后用它下载javascript文件,最后创建动态<script>元素将代码注入页面中。
例子:
var xhr = new XMLHttpRequest();
xhr.open("get","file.js",true);
xhr.onreadystatechange = function(){
if(xhr.readySate == 4){
//2xx表示有效响应,304表示从缓存中读取
if(xhr.status >= 200&&xhr.status < 300 || xhr.status == 304){
var script = document.createElement("script");
script.type = "text/javascript";
//用text相当于创建一个带有内联脚本的<script>标签
script.text = xhr.responseText;
document.body.sppendChild(script);
}
}
};
xhr.send(null);
主要优点:
javascript文件不会自动执行,你可以下载javascript文件但是不执行它,等到准备好的时候再执行。
同样的代码在主流浏览器中都能执行。
缺点:不能跨域请求js文件。
大型的web通常不是采用XHR脚本注入4)无阻塞模式(推荐)
向页面中添加大量javascript代码的推荐做法:两步
先添加动态加载所需的代码,越少越好;
然后加载初始化页面所需的剩余的代码。
方法一:
//加载loadScript函数
<script type="text/javascript" src = "loader.js"></script> <script type="text/script">
//"he-rest.js"剩余的javascript代码
loadScript("the-rest.js",function(){
Application.init();
})
</script>
//将这段代码放到</body>闭合标签之前。
方法二:直接将loadScript函数嵌入页面,产生一次HTTP请求。
放到下面代码之前:
<script type="text/script">
/*loadScript函数*/ .........
loadScript("the-rest.js",function(){ Application.init();
})
</script>
5)YUI3方式
6)LABjs方式。