请把以下用于连接字符串的JavaScript代码修改为更高效的方式:

var htmlString ='< div class=”container” > ' + '< ul id=”news-list” > ';
for (var i = 0; i < NEWS.length; i++) {
htmlString += '< li > < a href="' +NEWS[i].LINK +'" > +NEWS[i].TITLE + '< /a > < /li >';
}
htmlString += '< /ul > < /div > ';

zhiyelee的回答:

 
考点有两个:
  1. JavaScript的字符串连接机制。
  2. NEWS.length需要缓存,不然每次循环都要重新计算一次length
===============
主要看一下第一个:
在js里字符串一旦赋值后不能修改。
基于这个背景看一下字符串连接操作:
var str ;
str = 'this is a string';
str = str + ',another string.';

对于这个连接操作JS的处理机制是:新建一个临时字符串,将新字符串赋值为 str + ',another string.' ,然后返回这个新字符串并同时销毁原始字符串。所以字符串的连接效率较低。提高效率的办法是用数组的join函数:
var tempArr = [] ,src,res;
src = 'this is a string';
tempArr.push(src);
tempArr.push(',another string.');
res = tempArr.join('');
不过在《JavaScript高级程序设计》里也提到:
这个过程是在后台发生的,而这也是在某些旧版本的浏览器(例如版本低于1.0的FireFox、IE6等)中拼接字符串是速度很慢的原因。但这些浏览器后来的版本已经解决了这个问题。
所以效率提高也只是在IE6 等低版本的浏览器中有效。
 
————————————————————————————————————
关于此问题的更多知识,参考了hax的JS优化原则
 
高性能的String.format方法。String.format传统的实现方式是用String.replace(regex, func),在pattern包含n个占位符(包括重复的)时,自定义函数func就被调用n次。而这个高性能实现中,每次format调用所作的只是一次Array.join然后一次String.replace(regex, string)的操作,两者都是引擎内建方法,而不会有任何自定义函数调用。两次内建方法调用和n次的自定义方法调用,这就是性能上的差别。 

同样是内建特性,性能上也还是有差别的。例如在JScript中对于arguments的访问性能就很差,几乎赶上一次函数调用了。因此如果一个可变参数的简单函数成为性能瓶颈的时候,可以将其内部做一些改变,不要访问arguments,而是通过对参数的显式判断来处理。 

比如: 
function sum() {  
    var r = 0;  
    for (var i = 0; i < arguments.length; i++) {  
        r += arguments[i];  
    }  
    return r;  
}  

 
这个sum通常调用的时候个数是较少的,我们希望改进它在参数较少时的性能。如果改成: 
 
function sum() {  
    switch (arguments.length) {  
        case 1: return arguments[0];  
        case 2: return arguments[0] + arguments[1];  
        case 3: return arguments[0] + arguments[1] + arguments[2];  
        case 4: return arguments[0] + arguments[1] + arguments[2] + arguments[3];  
        default:  
            var r = 0;  
            for (var i = 0; i < arguments.length; i++) {  
                r += arguments[i];  
            }  
            return r;  
    }  
}  
其实并不会有多少提高,但是如果改成: 
function sum(a, b, c, d, e, f, g) {  
    var r = a ? b ? c ? d ? e ? f ? a + b + c + d + e + f : a + b + c + d + e : a + b + c + d : a + b + c : a + b : a : 0;  
    if (g === undefined) return r;  
    for (var i = 6; i < arguments.length; i++) {  
        r += arguments[i];  
    }  
    return r;  
}  
就会提高很多(至少快1倍)。 

最后是第五原则,也往往是真实应用中最重要的性能障碍,那就是尽量减少不必要的对象创建。 

本身创建对象是有一定的代价的,但是这个代价其实并不大。最根本的问题是由于JScript愚蠢之极的垃圾回收调度算法,导致随着对象个数的增加,性能严重下降(据微软的人自己说复杂度是O(n^2))。 

比如我们常见的字符串拼接问题,经过我的测试验证,单纯的多次创建字符串对象其实根本不是性能差的原因。要命的是在对象创建期间的无谓的垃圾回收的开销。而Array.join的方式,不会创建中间字符串对象,因此就减少了那该死的垃圾回收的开销。 

因此,如果我们能把大规模对象创建转化为单一语句,则其性能会得到极大的提高!例如通过构造代码然后eval——实际上PIES项目中正在根据这个想法来做一个专门的大规模对象产生器…… 

好了上面就是偶总结的JS优化五大原则。 

除了这些原则以外,还有一些特殊情况,如DOM的遍历,以后有时间再做讨论。

 

 

相关文章: