关于trim函数优化的问题

2010-05-08 Update:

突然对于第三种方法有些小想法,在循环内部通过使用正则来做判断和使用普通的!==符号来判断,孰好孰坏呢?说了不算,通过测试就知道结果如何了:《测试页面(短字符串:更新版)》,《测试页面(长字符串:更新版)》。

var trim=function(text){
    text=text.replace(/^\s+/,"");
    for(var i=text.length-1;i>=0;i--){
	 if(text.charAt(i) !== " "){  //key
	    text = text.substring(0,i+1);
	    break;
	  }
     }
     return text;
}

在各个浏览器下测试结果显示,通过使用!==符号来判断的时候,都获得了翻倍的性能提高,特别是比原第二第三种,无论是在短字符串和长字符串,都有所提高。不过在Chrome下,还是原第一种方式性能最高。

通过一个普普通通的小修改,让性能得到了比较大的提升,看来性能优化还得在细节上做文章。

根据上面的代码修改方式,再把代码小修改一下:

var trim=function(text){
    text=text.replace(/^\s+/,"");
    for(var i=text.length-1;i>=0;i--){
	 if(text[i] !== " "){   //key
	    text = text.substring(0,i+1);
	    break;
	  }
     }
     return text;
}

性能又得到了些许提高,哈哈~ 虽然普通,但是实用,能得到想要的性能提升。《测试页面(长)》,《测试页面(短)》。同时,通过测试,使用slice或者substring函数的性能相差无几。

==========================================================================

在javascript5之前版本中,没有提供内置的trim函数,确实是一门语言的缺陷。不过这个还是有很多变通的办法来处理的。在《高性能网站建设进阶指南》中,也提出了几种优化的方法。


第一种:就是我们通常使用正则的方式。书中解释说这种方式的性能方式主要在于正则的使用:一方面是指有两个匹配模式的管道运算符;另一方面是指明了全局应用该模式的g标记。

var trim=function(text){
    return text.replace(/^\s+|\s+$/g,"");
}

第二种:修改上面的实现方法,将单个的replace方法拆分为两次调用。书中说这样将每个正则表达式变得更简单,因此更快。

var trim=function(text){
   return text.replace(/^\s+/,"").replace(/\s+$/,"");
}

第三种:下面的这种方式是有Steven Levithan提出来的裁减字符串方式:

var trim=function(text){
   text=text.replace(/^\s+/,"");
   for(var i=text.length-1;i>=0;i--){
      if(/\S/.test(text.charAt(i))){
	  text = text.substring(0,i+1);
	  break;
      }
   }
   return text;
}

书中说上面的这种方式比上面的两种方式的性能都好,原因是保持了正则表达式尽可能地简单。第一行删除了头部的空白,然后通过for循环清除尾部的空白。循环使用一个非常简单的单字符串正则表达式来匹配非空白字符,它清除了字符串尾部的空白后退出循环。具体见:http://blog.stevenlevithan.com/archives/faster-trim-javascript

书中还说:裁剪字符串的速度只有在整个执行过程中裁剪的频率足够大时才重要。

对此,我有些感到疑惑:关于第一种方法的正则的性能消耗跟第二种调用了两个replace函数的性能消耗,究竟是孰少孰多?第三种中使用了第二种方法中的一个正则,之后又通过一个循环、判断、再一个简单的正则,这个跟上面的两种方法比起来,又孰少孰多?

对此,我进行了一个测试,使用长字符串和短字符串作为测试条件,测试效果图如下:(在Firefox下的结果,其他浏览器效果差异较小)《测试页面(短字符串)》,《测试页面(长字符串)


短字符串的测试结果


长字符串的测试结果

测试结果表明:(Firefox浏览器下的效果,关于长短字符串的界限,可以自行测试,^_^)

  1. 当需要裁剪的字符串是短字符串的时候,第二第三种方式并没有发挥性能提升的作用。这是因为字符串短,正则需要查询匹配的步骤少,所以相对比起调用replace和循环查询字符串来,性能消耗更小。
  2. 当需要裁剪的字符串是长字符串的时候,第二第三种方式神奇般地发挥了性能提升的作用。这个的原因跟上面相反。

但是有一点值得说明的是:在Chrome下,第一种方式始终是性能最高的。

大家的手印:

  1. 寸芒2010年05月8日于4:17 下午

    有用,学习之

  2. 女性免费试用网2010年05月8日于6:22 下午

    呵呵。我的站希望你也来光临

你的手印呢?