上海天缘迪柯信息技术有限公司
var images=document.getElementsByTagName(‘img’); for(var i=0,len=images.length;i 编写JavaScript的时候一定要知道何时返回NodeList对象,这样可以最小化对它们的访问 ? 进行了对getElementsByTagName()的调用 ? 获取了元素的childNodes属性 ? 获取了元素的attributes属性 ? 访问了特殊的集合,如document.forms、document.images等等 要了解了当使用NodeList对象时,合理使用会极大的提升代码执行速度 3.6.8 书写最优代码 3.6.8.1 避免不必要的属性查找 一旦多次用到对象属性,应该将其存储在局部变量中。一般来说,只要能减少算法的复杂度,就要尽可能减少,尽可能多的地使用局部变量将属性查找替换为值查找,进一步讲,使用[“”]查询要比.items()更快,这和前面的减少对象查找的思路是一样的,调用.items()增加了一次查询和函数的调用,如果既可以用数字化的数组位置进行访问,也可以使用命名属性,那么使用数字访问 3.6.8.2 优化循环 可以使用下面几种方式来优化循环 ? 减值迭代 大多数循环使用一个从0开始、增加到某个特定值的迭代器,在很多情况下,从最大值开始,在循环中不断减值的迭代器更加高效 ? 简化终止条件 由于每次循环过程都会计算终止条件,所以必须保证它尽可能快,也就是说避免属性查找或者其它的操作,最好是将循环控制量保存到局部变量中,也就是说对数组或列表对象的遍历时,提前将length保存到局部变量中,避免在循环的每一步重复取值。 例如: var list = document.getElementsByTagName('p'); 19 for (var i = 0; i < list.length; i++) { ?? } 替换为: var list = document.getElementsByTagName('p'); for (var i = 0, l = list.length; i < l; i++) { ?? } ? 简化循环体 循环体是执行最多的,所以要确保其被最大限度的优化 ? 使用后测试循环 在JavaScript中,我们可以使用for(;;),while(),for(in)三种循环,事实上,这三种循环中for(in)的效率极差,因为他需要查询散列键,只要可以,就应该尽量少用。for(;;)和while循环,while循环的效率要优于for(;;),可能是因为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]; } 最常用的for循环和while循环都是前测试循环,而如do-while这种后测试循环,可以避免最初终止条件的计算,因此运行更快。 3.6.8.3 展开循环 当循环次数是确定的,消除循环并使用多次函数调用往往会更快。 20 上海天缘迪柯信息技术有限公司 3.6.8.4 避免双重解释 如果要提高代码性能,尽可能避免出现需要按照JavaScript解释的字符串,也就是 ? 尽量少使用eval函数 使用eval相当于在运行时再次调用解释引擎对内容进行运行,需要消耗大量时间,而且使用Eval带来的安全性问题也是不容忽视的。 ? 不要使用Function构造器 ? 不要给setTimeout或者setInterval传递字符串参数 例如: var num = 0; setTimeout('num++', 10); 可以替换为: var num = 0; function addNum () { num++; } setTimeout(addNum, 10); 3.6.8.5 替换布尔值 考虑下面的例子 varbFound=false; for(var i=0;i 可以替换为: varbFound=0; for(var i=0;i if(aTest[i]==vTest) {bFound=1;} } 3.6.8.6 缩短否定检测 考虑到下面的例子 if(oTest !=#ff0000) { //do something } 21 if(oTest !=null) { //do something } if(oTest !=false) { //do something } 虽然这些都正确,但用逻辑非操作符来操作也有同样的效果: if(!oTest) { //do something } 3.6.8.7 条件分支 ? 将条件分支,按可能性顺序从高到低排列:可以减少解释器对条件的探测次数 ? 在同一条件子的多(>2)条件分支时,使用switch优于if:switch分支选择的 效率高于if,在IE下尤为明显。4分支的测试,IE下switch的执行时间约为if的一半。 ? 使用三目运算符替代条件分支 例如: if (a > b) { num = a; } else { num = b; } 可以替换为: num = a > b ? a : b; 3.6.8.8 在做字符查找替换等操作时善用正则表达式 3.6.9 内存管理 3.6.9.1 循环引用 如果循环引用中包含DOM对象或者ActiveX对象,那么就会发生内存泄露。内存泄露的后果是在浏览器关闭前,即使是刷新页面,这部分内存不会被浏览器释放。 22 上海天缘迪柯信息技术有限公司 简单的循环引用: 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'); 23