javascript 在浏览器中的性能成为开发者所面临的最重要的可用性问题。而这个问题又因 javascript 的阻塞特性变的复杂,也就是说当浏览器在执行 javascript 代码时,不能同时做其他任何事情。本文详细介绍了如何正确的加载和执行 javascript 代码,从而提高其在浏览器中的性能。
概览
无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成。JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长。浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或 JavaScript 的命名空间,它们对后面页面内容造成影响。一个典型的例子就是在页面中使用document.write()。
JavaScript 代码内嵌示例
Source Example
当浏览器遇到
立即学习“Java免费学习笔记(深入)”;
脚本位置
HTML 4 规范指出
低效率脚本位置示例
Source Example
Hello world!
然而这种常规的做法却隐藏着严重的性能问题。在清单 2 的示例中,当浏览器解析到
由于脚本会阻塞页面其他资源的下载,因此推荐将所有
推荐的代码放置位置示例
Source Example
Hello world!
这段代码展示了在 HTML 文档中放置
组织脚本
由于每个
这个问题在处理外链 JavaScript 文件时略有不同。考虑到 HTTP 请求会带来额外的性能开销,因此下载单个 100Kb 的文件将比下载 5 个 20Kb 的文件更快。也就是说,减少页面中外链脚本的数量将会改善性能。
通常一个大型网站或应用需要依赖数个 JavaScript 文件。您可以把多个文件合并成一个,这样只需要引用一个
需要特别提醒的是,把一段内嵌脚本放在引用外链样式表的 之后会导致页面阻塞去等待样式表的下载。这样做是为了确保内嵌脚本在执行时能获得最精确的样式信息。因此,建议不要把内嵌脚本紧跟在 标签后面。
无阻塞的脚本
减少 JavaScript 文件大小并限制 HTTP 请求数在功能丰富的 Web 应用或大型网站上并不总是可行。Web 应用的功能越丰富,所需要的 JavaScript 代码就越多,尽管下载单个较大的 JavaScript 文件只产生一次 HTTP 请求,却会锁死浏览器的一大段时间。为避免这种情况,需要通过一些特定的技术向页面中逐步加载 JavaScript 文件,这样做在某种程度上来说不会阻塞浏览器。
无阻塞脚本的秘诀在于,在页面加载完成后才加载 JavaScript 代码。这就意味着在 window 对象的 onload 事件触发后再下载脚本。有多种方式可以实现这一效果。
延迟加载脚本
HTML 4 为
defer 属性使用方法示例
带有 defer 属性的
任何带有 defer 属性的
defer 属性对脚本行为的影响
Script Defer Example
这段代码在页面处理过程中弹出三次对话框。不支持 defer 属性的浏览器的弹出顺序是:“defer”、“script”、“load”。而在支持 defer 属性的浏览器上,弹出的顺序则是:“script”、“defer”、“load”。请注意,带有 defer 属性的
如果您的目标浏览器只包括 Internet Explorer 和 Firefox 3.5,那么 defer 脚本确实有用。如果您需要支持跨领域的多种浏览器,那么还有更一致的实现方式。
HTML 5 为
动态脚本元素
采用 php+mysql 数据库方式运行的强大网上商店系统,执行效率高速度快,支持多语言,模板和代码分离,轻松创建属于自己的个性化用户界面 v3.5更新: 1).进一步静态化了活动商品. 2).提供了一些重要UFT-8转换文件 3).修复了除了网银在线支付其它支付显示错误的问题. 4).修改了LOGO广告管理,增加LOGO链接后主页LOGO路径错误的问题 5).修改了公告无法发布的问题,可能是打压
文档对象模型(DOM)允许您使用 JavaScript 动态创建 HTML 的几乎全部文档内容。
通过标准 DOM 函数创建
var script = document.createElement ("script");
script.type = "text/javascript";
script.src = "script1.js";
document.getElementsByTagName("head")[0].appendChild(script);新的
当文件使用动态脚本节点下载时,返回的代码通常立即执行(除了 Firefox 和 Opera,他们将等待此前的所有动态脚本节点执行完毕)。当脚本是“自运行”类型时,这一机制运行正常,但是如果脚本只包含供页面其他脚本调用调用的接口,则会带来问题。这种情况下,您需要跟踪脚本下载完成并是否准备妥善。可以使用动态
Firefox、Opera, Chorme 和 Safari 3+会在
通过监听 onload 事件加载 JavaScript 脚本
var script = document.createElement ("script")
script.type = "text/javascript";
//Firefox, Opera, Chrome, Safari 3+
script.onload = function(){
alert("Script loaded!");
};
script.src = "script1.js";
document.getElementsByTagName("head")[0].appendChild(script);Internet Explorer 支持另一种实现方式,它发出一个 readystatechange 事件。
微软文档上说,在
通过检查 readyState 状态加载 JavaScript 脚本
var script = document.createElement("script")
script.type = "text/javascript";
//Internet Explorer
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
alert("Script loaded.");
}
};
script.src = "script1.js";
document.getElementsByTagName("head")[0].appendChild(script);大多数情况下,您希望调用一个函数就可以实现 JavaScript 文件的动态加载。下面的函数封装了标准实现和 IE 实现所需的功能:
通过函数进行封装
function loadScript(url, callback){
var script = document.createElement ("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}此函数接收两个参数:JavaScript 文件的 URL,和一个当 JavaScript 接收完成时触发的回调函数。属性检查用于决定监视哪种事件。最后一步,设置 src 属性,并将
loadScript()函数使用方法
loadScript("script1.js", function(){
alert("File is loaded!");
});您可以在页面中动态加载很多 JavaScript 文件,但要注意,浏览器不保证文件加载的顺序。所有主流浏览器之中,只有 Firefox 和 Opera 保证脚本按照您指定的顺序执行。其他浏览器将按照服务器返回它们的次序下载并运行不同的代码文件。您可以将下载操作串联在一起以保证他们的次序,如下:
通过 loadScript()函数加载多个 JavaScript 脚本
loadScript("script1.js", function(){
loadScript("script2.js", function(){
loadScript("script3.js", function(){
alert("All files are loaded!");
});
});
});此代码等待 script1.js 可用之后才开始加载 script2.js,等 script2.js 可用之后才开始加载 script3.js。虽然此方法可行,但如果要下载和执行的文件很多,还是有些麻烦。如果多个文件的次序十分重要,更好的办法是将这些文件按照正确的次序连接成一个文件。独立文件可以一次性下载所有代码(由于这是异步进行的,使用一个大文件并没有什么损失)。
动态脚本加载是非阻塞 JavaScript 下载中最常用的模式,因为它可以跨浏览器,而且简单易用。
使用 XMLHttpRequest(XHR)对象
此技术首先创建一个 XHR 对象,然后下载 JavaScript 文件,接着用一个动态
通过 XHR 对象加载 JavaScript 脚本
var xhr = new XMLHttpRequest();
xhr.open("get", "script1.js", true);
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
var script = document.createElement ("script");
script.type = "text/javascript";
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
xhr.send(null);此代码向服务器发送一个获取 script1.js 文件的 GET 请求。 onreadystatechange 事件处理函数检查 readyState 是不是 4,然后检查 HTTP 状态码是不是有效(2XX 表示有效的回应,304 表示一个缓存响应)。如果收到了一个有效的响应,那么就创建一个新的
这种方法的主要优点是,您可以下载不立即执行的 JavaScript 代码。由于代码返回在
此方法最主要的限制是:JavaScript 文件必须与页面放置在同一个域内,不能从 CDN 下载(CDN 指"内容投递网络(Content Delivery Network)",所以大型网页通常不采用 XHR 脚本注入技术。
总结
减少 JavaScript 对性能的影响有以下几种方法:
通过以上策略,可以在很大程度上提高那些需要使用大量 JavaScript 的 Web 网站和应用的实际性能。
原文来自:http://www.php.cn/
补充js加载函数:
function loadJs(url, callback, charset) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
if ( !!charset) script.charset = "utf-8";
script.src = url;
script.onload = script.onreadystatechange = function() {
var f = script.readyState;
if (f && f != "loaded" && f != "complete") return;
script.onload = script.onreadystatechange = null;
head.removeChild(script) if (callback) {
callback() || callback
};
};
head.appendChild(script);
}// js同步加载
function getScripts(i, linkArray, fn) {
env || getEnv();
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = linkArray[i];
var head = document.head || document.getElementsByTagName('head')[0];
head.appendChild(script);
if (env.ie && 'onreadystatechange' in script && !('draggable' in script)){ //ie浏览器使用以下方式加载
script.onreadystatechange = function () {
if (/loaded|complete/.test(script.readyState)) {
script.onreadystatechange = null;
if(i === linkArray.length-1) {
if (fn) {
fn();
}
} else {
getScripts(++i, linkArray, fn);
}
}
};
}else{
script.onload = function() {
if(i === linkArray.length-1) {
if (fn) {
fn();
}
} else {
getScripts(++i, linkArray, fn);
}
};
}
}// js存在依赖关系 依次加载
getScripts(0, [
'http://caibaojian.com/demo/base.js',
'http://caibaojian.com/demo/reset.js'], function() {
alert('callback');
});以上就是加快JavaScript加载和执行效率的内容,更多相关内容请关注PHP中文网(www.php.cn)!










