`
cloudtech
  • 浏览: 4613294 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

[转] 提高JS性能注意事项

 
阅读更多
一.执行效率
1. DOM
1.1 使用DocumentFragment优化多次append
说明:添加多个dom元素时,先将元素append到DocumentFragment中,最后统一将DocumentFragment添加到页面。
该做法可以减少页面渲染dom元素的次数。经IE和Fx下测试,在append1000个元素时,效率能提高10%-30%,Fx下提升较为明显。

服用前:
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p');
el.innerHTML = i;
document.body.appendChild(el);
}

服用后:
var frag = document.createDocumentFragment();
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p');
el.innerHTML = i;
frag.appendChild(el);
}
document.body.appendChild(frag);

1.2 通过模板元素clone,替代createElement
说明:通过一个模板dom对象cloneNode,效率比直接创建element高。
性能提高不明显,约为10%左右。在低于100个元素create和append操作时,没有优势。

服用前:
var frag = document.createDocumentFragment();
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p');
el.innerHTML = i;
frag.appendChild(el);
}
document.body.appendChild(frag);

服用后:
var frag = document.createDocumentFragment();
var pEl = document.getElementsByTagName('p')[0];
for (var i = 0; i < 1000; i++) {
var el = pEl.cloneNode(false);
el.innerHTML = i;
frag.appendChild(el);
}
document.body.appendChild(frag);

1.3 使用一次innerHTML赋值代替构建dom元素
说明:根据数据构建列表样式的时候,使用设置列表容器innerHTML的方式,比构建dom元素并append到页面中的方式,效率有数量级上的提高。

服用前:
var frag = document.createDocumentFragment();
for (var i = 0; i < 1000; i++) {
var el = document.createElement('p');
el.innerHTML = i;
frag.appendChild(el);
}
document.body.appendChild(frag);

服用后:
var html = [];
for (var i = 0; i < 1000; i++) {
html.push('<p>' + i + '</p>');
}
document.body.innerHTML = html.join('');

1.4 使用firstChild和nextSibling代替childNodes遍历dom元素
说明:约能获得30%-50%的性能提高。逆向遍历时使用lastChild和previousSibling。

服用前:
var nodes = element.childNodes;
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
……
}

服用后:
var node = element.firstChild;
while (node) {
……
node = node.nextSibling;
}


2. 字符串

2.1 使用Array做为StringBuffer,代替字符串拼接的操作
说明:IE在对字符串拼接的时候,会创建临时的String对象;经测试,在IE下,当拼接的字符串越来越大时,运行效率会急剧下降。Fx和Opera都对字符串拼接操作进行了优化;经测试,在Fx下,使用Array的join方式执行时间约为直接字符串拼接的1.4倍。

服用前:
var now = new Date();
var str = '';
for (var i = 0; i < 10000; i++) {
str += '123456789123456789';
}
alert(new Date() - now);

服用后:
var now = new Date();
var strBuffer = [];
for (var i = 0; i < 10000; i++) {
strBuffer.push('123456789123456789');
}
var str = strBuffer.join('');
alert(new Date() - now);


3. 循环语句

3.1 将循环控制量保存到局部变量
说明:对数组和列表对象的遍历时,提前将length保存到局部变量中,避免在循环的每一步重复取值。

服用前:
var list = document.getElementsByTagName('p');
for (var i = 0; i < list.length; i++) {
……
}

服用后:
var list = document.getElementsByTagName('p');
for (var i = 0, l = list.length; i < l; i++) {
……
}


3.2 顺序无关的遍历时,用while替代for
说明:该方法可以减少局部变量的使用。比起效率优化,更能直接看到的是字符数量的优化。该做法有程序员强迫症的嫌疑。

服用前:
var arr = [1,2,3,4,5,6,7];
var sum = 0;
for (var i = 0, l = arr.length; i < l; i++) {
sum += arr[i];
}

服用后:
var arr = [1,2,3,4,5,6,7];
var sum = 0, l = arr.length;
while (l--) {
sum += arr[l];
}

4. 条件分支

4.1 将条件分支,按可能性顺序从高到低排列
说明:可以减少解释器对条件的探测次数。

4.2 在同一条件子的多(>2)条件分支时,使用switch优于if
说明:switch分支选择的效率高于if,在IE下尤为明显。4分支的测试,IE下switch的执行时间约为if的一半。

4.3 使用三目运算符替代条件分支
服用前:
if (a > b) {
num = a;
} else {
num = b;
}

服用后:
num = a > b ? a : b;


5. 定时器

5.1 需要不断执行的时候,优先考虑使用setInterval
说明:setTimeout每一次都会初始化一个定时器。setInterval只会在开始的时候初始化一个定时器

服用前:
var timeoutTimes = 0;
function timeout () {
timeoutTimes++;
if (timeoutTimes < 10) {
setTimeout(timeout, 10);
}
}
timeout();

服用后:
var intervalTimes = 0;
function interval () {
intervalTimes++;
if (intervalTimes >= 10) {
clearInterval(interv);
}
}
var interv = setInterval(interval, 10);

5.2 使用function而不是string
说明:如果把字符串作为setTimeout和setInterval的参数,浏览器会先用这个字符串构建一个function。

服用前:
var num = 0;
setTimeout('num++', 10);

服用后:
var num = 0;
function addNum () {
num++;
}
setTimeout(addNum, 10);


6. 其他

6.1 尽量不使用动态语法元素
说明:eval、Function、execScript等语句会再次使用javascript解析引擎进行解析,需要消耗大量的执行时间。

6.2 重复使用的调用结果,事先保存到局部变量
说明:避免多次取值的调用开销。

服用前:
var h1 = element1.clientHeight + num1;
var h2 = element1.clientHeight + num2;

服用后:
var eleHeight = element1.clientHeight;
var h1 = eleHeight + num1;
var h2 = eleHeight + num2;

6.3 使用直接量
说明:
var a = new Array(param,param,...) -> var a = []
var foo = new Object() -> var foo = {}
var reg = new RegExp() -> var reg = /.../

6.4 避免使用with
说明: with虽然可以缩短代码量,但是会在运行时构造一个新的scope。
OperaDev上还有这样的解释,使用with语句会使得解释器无法在语法解析阶段对代码进行优化。对此说法,无法验证。

服用前:
with (a.b.c.d) {
property1 = 1;
property2 = 2;
}


服用后:
var obj = a.b.c.d;
obj.property1 = 1;
obj.property2 = 2;


6.5 巧用||和&&布尔运算符
重要程度:★★★

服用前:
function eventHandler (e) {
if(!e) e = window.event;
}


服用后:
function eventHandler (e) {
e = e || window.event;
}


服用前:
if (myobj) {
doSomething(myobj);
}


服用后:
myobj && doSomething(myobj);


6.6 类型转换
说明:
1). 数字转换成字符串,应用"" + 1,性能上:("" +) > String() > .toString() > new String();
2). 浮点数转换成整型,不使用parseInt(), parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换,建议使用Math.floor()或者Math.round()
3). 对于自定义的对象,推荐显式调用toString()。内部操作在尝试所有可能性之后,会尝试对象的toString()方法尝试能否转化为String。


二.内存管理

2.1 循环引用
说明:如果循环引用中包含DOM对象或者ActiveX对象,那么就会发生内存泄露。内存泄露的后果是在浏览器关闭前,即使是刷新页面,这部分内存不会被浏览器释放。

简单的循环引用:
var el = document.getElementById('MyElement');
var func = function () {…}
el.func = func;
func.element = el;


但是通常不会出现这种情况。通常循环引用发生在为dom元素添加闭包作为expendo的时候。

如:
function init() {
var el = document.getElementById('MyElement');
el.onclick = function () {……}
}
init();


init在执行的时候,当前上下文我们叫做context。这个时候,context引用了el,el引用了function,function引用了context。这时候形成了一个循环引用。

下面2种方法可以解决循环引用:

1) 置空dom对象

服用前:
function init() {
var el = document.getElementById('MyElement');
el.onclick = function () {……}
}
init();


服用后:
function init() {
var el = document.getElementById('MyElement');
el.onclick = function () {……}
el = null;
}
init();


将el置空,context中不包含对dom对象的引用,从而打断循环应用。
如果我们需要将dom对象返回,可以用如下方法:

服用前:
function init() {
var el = document.getElementById('MyElement');
el.onclick = function () {……}
return el;
}
init();


服用后:
function init() {
var el = document.getElementById('MyElement');
el.onclick = function () {……}
try{
return el;
} finally {
el = null;
}
}
init();

2) 构造新的context
服用前:
function init() {
var el = document.getElementById('MyElement');
el.onclick = function () {……}
}
init();


服用后:
function elClickHandler() {……}
function init() {
var el = document.getElementById('MyElement');
el.onclick = elClickHandler;
}
init();

把function抽到新的context中,这样,function的context就不包含对el的引用,从而打断循环引用。

2.2 通过javascript创建的dom对象,必须append到页面中
说明:IE下,脚本创建的dom对象,如果没有append到页面中,刷新页面,这部分内存是不会回收的!

示例代码:

function create () {
var gc = document.getElementById('GC');
for (var i = 0; i < 5000 ; i++)
{
var el = document.createElement('div');
el.innerHTML = "test";

//下面这句可以注释掉,看看浏览器在任务管理器中,点击按钮然后刷新后的内存变化
gc.appendChild(el);
}
}


2.3 释放dom元素占用的内存
说明:
将dom元素的innerHTML设置为空字符串,可以释放其子元素占用的内存。
在rich应用中,用户也许会在一个页面上停留很长时间,可以使用该方法释放积累得越来越多的dom元素使用的内存。

2.4 释放javascript对象
说明:在rich应用中,随着实例化对象数量的增加,内存消耗会越来越大。所以应当及时释放对对象的引用,让GC能够回收这些内存控件。
对象:obj = null
对象属性:delete obj.myproperty
数组item:使用数组的splice方法释放数组中不用的item

2.5 避免string的隐式装箱
说明:对string的方法调用,比如'xxx'.length,浏览器会进行一个隐式的装箱操作,将字符串先转换成一个String对象。推荐对声明有可能使用String实例方法的字符串时,采用如下写法:
var myString = new String('Hello World');
分享到:
评论

相关推荐

    实现高性能javascript的注意事项

    1.少用全局变量 ...原因:正如前面所说,活动对象在栈的顶端,所以最先查找它的内容,当我们将document封装成局部变量后就会减少深层次查找的次数,使性能提高。 3.操作数组长度、对象属性时,尽量使用局部变量封

    优化JavaScript脚本的性能的几个注意事项

    所以能无法达到和C/Java之类的水平,限制了它能在客户端所做的事情,为了能改进他的性能,我想基于我以前给JavaScript做过的很多测试来谈谈自己的经验,希望能帮助大家改进自己的JavaScript脚本性能。 语言层次方面 ...

    JavaScript脚本性能优化注意事项

    本文总结了我在JavaScript编程中所找到的提高JavaScript运行性能的一些方法,其实这些经验都基于几条原则

    7个让JavaScript变得更好的注意事项

    随着浏览器性能提高,伴随着新的HTML5的编程接口的稳步采用,网页上的JavaScript的音量在逐渐增加。然而,一个写得不好的程序编码却拥有着打破整个网站,让用户为之沮丧和驱赶潜在客户的潜力。  开发人员必须使用...

    util-js-optihelp:FutoIn软件包优化助手

    文档-&gt; 作者:安装Node.js 命令行: $ npm install @futoin/optihelp --save 或者: $ yarn add @futoin/optihelp --save概念与注意事项每个CPU模型和Node.js版本的测试都是唯一的。 结合使用SHA-256哈希进行混淆,...

    具有ESBuild和TypeScript的Sapper模板-JavaScript开发

    带有ESBuild和TypeScript的Sapper模板Sapper Typescript ESBuild这是一个最小的Sapper项目模板,其...入门npm install npm run dev导出npm run export export注意事项如果使用Sapper 0.28,则服务器代码压缩功能被禁用

    node-express-sqllite3:使用node,express和sqllite3作为数据库的小型项目

    SWS API-CompanySWS API NodeJS v8.4.0 + Express + SQLite设置安装npm i测试npm t跑步npm start注意事项在波动搜索中,我只进行了90天以上的查询,因为数据库中有ont记录解决方案的大多数决定是考虑性能。...

    JAVA毕业设计之springboot网上图书商城项目(springboot完整源码+说明).zip

    总之,这个Spring Boot网上图书商城项目资源是一个非常有价值的学习资料,不仅可以帮助您掌握Spring Boot框架的开发技能,还可以帮助您深入了解一个完整的Web应用项目的开发流程和注意事项。希望这个资源能够对您的...

    ergodox-vim-ubuntu:针对Vim和Ubuntu使用进行了优化的Ergodox EZ布局

    时间(天) 打字速度(wpm) 相对表现+1 8 18% +7 22 49% +14 35 78% +28 47 105% +56 58 129%注意事项这种布局是为Vim用户设计的,还包含一些映射,以便于我经常使用的Ubuntu工作区轻松导航。 我主要使用Java...

    gatsby-intro:盖茨比课程入门代码

    前端大师:盖茨比简介在本课程中,学习使用Gatsby(一个静态PWA(渐进式Web应用程序)生成器)使用React构建出色的快速应用程序和网站。 如果加载时间超过3秒,则超过...关于运行代码的注意事项我们建议上以建立使用Ga

    asp.net知识库

    .net 2.0 访问Oracle --与Sql Server的差异,注意事项,常见异常 Ado.net 与NHibernate的关系? 动态创建数据库 SQL Server数据库安全规划全攻略 .net通用数据库访问组件SQL Artisan应用简介1 在Framework1.0下...

    community-gardens

    社区花园 社区花园是关于北卡罗来纳州立大学学生体内食物和住房不安全的一种生成艺术经验。 在过去的一年中,有9.6%的... 处理能力和内存大小:有关基于GPU和设备类型的性能的一些注意事项,请参阅。 连接性:项目可

    reboot-pbf:重新启动是捐赠和购买使用Django构建的新旧橄榄球靴的交换

    对于大三学生来说,脚的长大是更换靴子的主要原因,而成年人可能希望通过换鞋来提高性能或解决磨损问题。 无论年龄或性别,Re-Boot都致力于以低廉的价格和高品质的替换靴为橄榄球比赛社区提供服务,而其价格仅为...

    ProductivityApp:拜托! 社会希望我们尽可能地提高生产力,那么,为什么不帮助它呢? 我对此有一些问题,但是我最终决定我想与“待办事项”列表一起工作,而不仅仅是纸质工作列表。 为什么不加入学习React.js呢? 听起来像一个挑战!

    它在生产模式下正确捆绑了React,并优化了构建以获得最佳性能。 生成被最小化,并且文件名包括哈希值。 您的应用已准备好进行部署! 有关更多信息,请参见关于的部分。 npm run eject 注意:这是单向操作。 ...

    创易CreateEasy CMS V1.0 SP7.rar

    主要特性: 1、基于ASP ACCESS/SQLSERVER的技术构建,支持全生成静态文件,加速你的网站访问速度,...注意事项: 该补丁针对的是创易CreateEasy CMS V1.0 SP6版系统用户,其他版本用户请升级至SP6系统后使用该补丁!

    庖丁解牛纵向切入ASP.NET 3.5控件和组件开发技术.pdf

    3.8.8 使用createchildcontrols的注意事项56 3.8.9 不要误解设计元属性defaultvalue57 3.8.10 在render方法中利用基类资源57 3.8.11 条件编译&条件属性60 3.9 本章总结61 第4章 服务器控件属性62 4.1 控件属性...

    华西网源码

    这个并不会对模板对性能方面有什么任何改变,这是通过这个提高了模板的安全性,使别人不能随意盗用模板 如果不想保留仿购网的版权信息可以将里面的代码删除 但是一定要保留这个代码啊 ;?&gt; 2.修改使用说明: 1...

    YIXUNCMS网站建设系统

    注意事项 1、共享版软件只适合试用、本地测试及学习交流使用,不得用于商业用途,如需建立商业站点进行外网投放,请使用购买商业版; 2、您可以在遵守本协议规定和约束的基础上,对软件进行程序修改、页面美化,以...

    互联网创意产品众筹平台

    │ 10-模糊查询-注意事项 │ 11-附录1.JS中局部变量和全局变量区别 │ d( L, Z2 p" ] ├─众筹项目-第05天《Atcrowdfunding》) A% ]3 K. N. T& e) [7 J │ ├─代码 │ ├─笔记 │ └─视频2 @8 e5 L% ~) b6 _) f....

    网管教程 从入门到精通软件篇.txt

    网管教程 从入门到精通软件篇 ★一。★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 ...JS:javascript源文件 JSP:HTML网页,其中包含有对一个Java servlet...

Global site tag (gtag.js) - Google Analytics