作者 Mark 'Tarquin' Wilton-Jones · 2006年11月2日
本文翻译自 Efficient JavaScript
原译文地址 http://kb.operachina.com/node/207
传统上,网页中不会有大量的脚本,至少脚本很少会影响网页的性能。但随着网页越来越像 Web 应用程序,脚本的效率对网页性能影响越来越大。而且使用 Web 技术开发的应用程序现在越来越多,因此提高脚本的性能变得很重要。
对于桌面应用程序,通常使用编译器将源代码转换为二进制程序。编译器可以花费大量时间优化最终二进制程序的效率。Web 应用程序则不同。因为Web应用程序需要运行在不同的浏览器、平台和架构中,不可能事先完全编译。浏览器在获得脚本后要执行解释和编译工作。用户要求不仅要求网页能快速的载入,而且要求最终 Web 应用程序执行的效果要和桌面应用程序的一样流畅。Web 应用程序应能运行在多种设备上,从普通的桌面电脑到手机。
浏览器并不很擅长此项工作。虽然 Opera 有着当前最快的脚本引擎,但浏览器有不可避免的局限性,这时就需要 Web 开发者的帮助。Web开发者提高 Web 应用程序的性能的方法很多而且也很简单,如只需要将一种循环变成另一种、将组合样式分解成三个或者只添加实际需要的脚本。
本文从 ECMAScript/JavaScript, DOM, 和页面载入方面分别介绍几种简单的能提高 Web 应用程序性能的方法。
eval 或 Function 构造函数
with
try-catch-finally
eval 和 with
eval 或 Function 构造函数0
eval 或 Function 构造函数1 eval 或 Function 构造函数每次 eval 或 with 构造函数作用于字符串表示的源代码时,脚本引擎都需要将源代码转换成可执行代码。这是很消耗资源的操作 —— 通常比简单的函数调用慢100倍以上。
try-catch-finally 函数效率特别低,由于事先无法知晓传给 eval 的字符串中的内容,with在其上下文中解释要处理的代码,也就是说编译器无法优化上下文,因此只能有浏览器在运行时解释代码。这对性能影响很大。
for-in 构造函数比 setTimeout() 略好,因为使用此代码不会影响周围代码;但其速度仍很慢。
setInterval()
location.replace() 不仅效率低下,而且绝大部分情况下完全没有使用的必要。很多情况下使用 eval 是因为信息以字符串形式提供,开发者误认为只有 eval 能使用此信息。下例是一个典型的错误:
eval 或 Function 构造函数2的方式,最好还是尽量保持快速历史浏览功能。也就是说最好避免会影响此功能的动作,包括提交表单时禁用表单控件或让页面内容透明或不可见的渐出特效。
简单的解决方法是使用 onunload 监听器 reset 渐出效果或重新 enable 表单控件。注意对有些浏览器来说,如 Firefox 和 Safari,为 unload 事件添加监听器会禁用历史浏览。而在 Opera 中禁用提交按钮会导致禁用历史浏览。
此技巧不一定适用于每一个项目,但它能显著降低从服务器下载数据量,也能避免重载页面时销毁及创建脚本环境的开销。开始时正常载入页面,然后使用 XMLHttpRequest 下载最少量的新内容。这样 JavaScript 环境会一直存在。
启科网络商城系统由启科网络技术开发团队完全自主开发,使用国内最流行高效的PHP程序语言,并用小巧的MySql作为数据库服务器,并且使用Smarty引擎来分离网站程序与前端设计代码,让建立的网站可以自由制作个性化的页面。 系统使用标签作为数据调用格式,网站前台开发人员只要简单学习系统标签功能和使用方法,将标签设置在制作的HTML模板中进行对网站数据、内容、信息等的调用,即可建设出美观、个性的网站。
0
注意此方法也可能会导致问题。首先此方法完全破坏历史浏览。尽管可通过内联frame储存信息来解决此问题,但这显然不符合使用XMLHttpRequest 的初衷。因此尽量少用,只在不需要回退到先前内容时使用。此方法还会影响辅助器具的使用( assistivedevice),因为将无法察觉 DOM 已被更改,因此最好在不会引起问题的地方使用XMLHttpRequest。
若 JavaScript 不可用或不支持 XMLHttpRequest则此技巧也会失效。最简单避免此问题的方法是使用正常链接指向新页面。增加一个检测链接是否被激活的事件处理器。处理器可以探测是否支持XMLHttpRequest ,如果支持则载入新数据并阻止链接默认动作。载入新数据后,用其取代页面的部分内容,然后 request对象就可以被销毁并允许垃圾收集器回收内存资源。
加载和处理脚本需要时间,但有些脚本在载入后却从来未被使用。载入这样的脚本浪费时间和资源,并影响当前的脚本执行,因此最好不要引用这种不用的脚本。可以通过简单的加载脚本判断需要哪些脚本,并只为后面需要的脚本创建 script 元素。
理论上,这个加载脚本可在页面载入结束后通过创建 SCRIPT 元素加入 DOM。这在所有主流浏览器中都可以正常工作,但这可能对浏览器的提出更多的要求,甚至大于要载入的脚本本身。而且在页面载入之前可能就需要脚本,因此最好在页面加载过程中,通过eval 创建 script 标签。记住一定要转义‘/'字符防止终止当前脚本运行:
Function 控制历史项有时需要通过脚本修改页面地址。常见的方法是给eval 赋新地址。这将和打开新链接一样添加新历史项、载入新页面。
有时不想添加新历史项,因为用户不需要回到前面的页面。这在内存资源有限的设备中很有用。通过替换历史项恢复当前页面所使用的内存。可以通过 Function方法实现。
注意页面仍被保存在 cache 中,仍占用内存,但比保存在历史中要少的多。
<PRE class=brush:javascript>var testObject = test.information.settings.files; testObject.primary = 'names'; testObject.secondary = 'roles'; testObject.tertiary = 'references';
var oProperties = ['first','second','third',...,'nth'], i;
try {
for( i = 0; i < oProperties.length; i++ ) {
test[oProperties[i]].someproperty = somevalue;
}
} catch(e) {
...
}
function testfunction() {
var i, s = '';
for( i = 0; i < 20; i++ ) {
s += i;
}
}
testfunction();
var s = '0123456789';
for( var i = 0; i < s.length; i++ ) {
s.charAt(i);
}
setInterval(updateResults,1000);
setTimeout(function () {
x += 3;
prepareResult();
if( !hasCancelled ) {
runmore();
}
},500);
div {
background: #ddd;
color: #000;
border: 1px solid #000;
}
div.highlight {
background: #333;
color: #fff;
border: 1px solid #00f;
}
...
document.getElementById('mainelement').className = 'highlight';
if( document.evaluate ) {
var headings = document.evaluate( '//h2|//h3|//h4', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
var oneheading;
while( oneheading = headings.iterateNext() ) {
...
}
} else {
var allElements = document.getElementsByTagName('*');
for( var i = 0; i < allElements.length; i++ ) {
if( allElements[i].tagName.match(/^h[2-4]$/i) ) {
...
}
}
}
var allPara = document.getElementsByTagName('p');
for( var i = 0; i < allPara.length; i++ ) {
allPara[i].appendChild(document.createTextNode(i));
}
var allPara = document.getElementsByTagName('p');
var collectTemp = [];
for( var i = 0; i < allPara.length; i++ ) {
collectTemp[collectTemp.length] = allPara[i];
}
for( i = 0; i < collectTemp.length; i++ ) {
collectTemp[i].appendChild(document.createTextNode(i));
}
collectTemp = null;
java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号