本文汇总了JavaScript中去除字符串空格的12种实现方式,从简单的正则替换到复杂的原生方法遍历。通过对比Firefox 2与IE 6在长字符串处理下的执行时间,揭示了不同实现的性能差异。推荐使用基于indexOf与substring的高性能方案,或结合正则与原生方法的平衡方案,以兼顾代码可读性与执行效率。
JavaScript去除空格的12种实现方案
实现方案1
具体代码实现如下:
String.prototype.trim = function () {
return this .replace(/^\s\s*/, '' ).replace(/\s\s*$/, '' );
} 该实现看似仅动用了两次正则替换,效果平平,但实际运行速度却极为惊人。这主要归功于浏览器内部的优化机制。一个著名的例子是字符串拼接,直接相加的速度甚至快于使用Array模拟的StringBuffer。base2类库便采用了这种实现方式。
实现方案2
具体代码实现如下:
String.prototype.trim = function () {
return this .replace(/^\s+/, '' ).replace(/\s+$/, '' );
} 此方案与实现1相似,但速度稍慢。主要原因在于它假设字符串中至少存在一个空白符。Prototype.js采用了这种实现,但将其命名为strip,因为Prototype的方法力求与Ruby语言中的同名方法保持一致。
实现方案3
具体代码实现如下:
String.prototype.trim = function () {
return this .substring(Math.max( this .search(/\S/), 0), this .search(/\S\s*$/) + 1);
} 该方案通过截取方式获取非空白部分(允许中间存在空白符),共调用了四个原生方法。设计十分巧妙,substring接收两个数字作为参数,Math.max接收两个数字,search返回一个数字。其速度比前两种方案稍慢,但快于后续大多数实现。
实现方案4
具体代码实现如下:
String.prototype.trim = function () {
return this .replace(/^\s+|\s+$/g, '' );
} 这可以视为实现2的简化版,利用候选操作符连接两个正则表达式。然而,这种做法失去了浏览器优化的机会,性能不如实现3。尽管代码看起来非常优雅,许多类库如JQuery与mootools都采用了它。
实现方案5
具体代码实现如下:
String.prototype.trim = function () {
var str = this ;
str = str.match(/\S+(?:\s+\S+)*/);
return str ? str[0] : '' ;
} match返回一个数组,因此符合要求的原字符串部分成为其元素。为防止字符串中间的空白符被排除,需使用非捕获性分组(?:exp)。由于数组可能为空,后续还需进行判定。浏览器在处理分组时表现较为无力,导致速度较慢。因此,不要迷信正则表达式,尽管它通常被视为万能工具。
实现方案6
具体代码实现如下:
String.prototype.trim = function () {
return this .replace(/^\s*(\S*(\s+\S+)*)\s*$/, '$1' );
} 该方案将符合要求的部分提取出来,放入一个空字符串中。不过效率较差,尤其在IE 6环境中表现明显。
实现方案7
具体代码实现如下:
String.prototype.trim = function () {
return this .replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, '$1' );
} 此方案与实现6相似,但使用了非捕获分组,性能略有提升。
实现方案8
具体代码实现如下:
String.prototype.trim = function () {
return this .replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1' );
} 沿袭前两个方案的思路进行改进,使用了非捕获分组与字符集合,用?替代了*,效果惊人。尤其在IE 6中,性能提升可以用“疯狂”来形容,直接超越了Firefox。
实现方案9
具体代码实现如下:
String.prototype.trim = function () {
return this .replace(/^\s*([\S\s]*?)\s*$/, '$1' );
} 此处使用懒惰匹配替代非捕获分组,在Firefox中得到改善,但在IE中不如上次提升那么显著。
实现方案10
具体代码实现如下:
String.prototype.trim = function () {
var str = this ,
whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000' ;
for ( var i = 0,len = str.length; i < len; i++) {
if (whitespace.indexOf(str.charAt(i)) === -1) {
str = str.substring(i);
break ;
}
}
for (i = str.length - 1; i >= 0; i--) {
if (whitespace.indexOf(str.charAt(i)) === -1) {
str = str.substring(0, i + 1);
break ;
}
}
return whitespace.indexOf(str.charAt(0)) === -1 ? str : '' ;
} 创造此方案的人堪称神级。它首先列出所有可能的空白符,在第一次遍历中去除前导空白,第二次去除尾部空白。全过程仅使用indexOf与substring这两个专为字符串处理设计的原生方法,未使用正则表达式。速度惊人,估计直逼内部二进制实现,且在IE与Firefox(及其他浏览器)中均有良好表现,速度均为零毫秒级别。
实现方案11
具体代码实现如下:
String.prototype.trim = function () {
var str = this ,
str = str.replace(/^\s+/, '' );
for ( var i = str.length - 1; i >= 0; i--) {
if (/\S/.test(str.charAt(i))) {
str = str.substring(0, i + 1);
break ;
}
}
return str;
} 实现10已证明普通原生字符串截取方法远胜于正则替换,尽管代码稍显复杂。只要正则表达式不过于复杂,即可利用浏览器对正则的优化来提升效率,如实现8在IE中的表现。通常项目中不会直接应用实现10,因为其whitespace变量定义过长且难以记忆(除非在打造类库,此时它是首选)。实现11是其改进版,前导空白由正则替换处理,尾部空白由原生方法处理,效果不逊于原版,且速度极快。
实现方案12
具体代码实现如下:
String.prototype.trim = function () {
var str = this ,
str = str.replace(/^\s\s*/, '' ),
ws = /\s/,
i = str.length;
while (ws.test(str.charAt(--i)));
return str.slice(0, i + 1);
} 这是实现10与实现11在写法上的更优改进版,注意这里强调的是易记性与使用便捷性,而非性能速度。它与前两位前辈一样,速度均为零毫秒级别,可作为日常开发与“吓人”效果的首选。
不同方案的性能对比分析
以下是国外开发者给出的比较结果,测试背景是对一篇名为Magna Carta的文章(超过27,600字符)进行trim操作。
实现方案 Firefox 2 IE 6
trim1 15ms < 0.5ms
trim2 31ms < 0.5ms
trim3 46ms 31ms
trim4 47ms 46ms
trim5 156ms 1656ms
trim6 172ms 2406ms
trim7 172ms 1640ms
trim8 281ms < 0.5ms
trim9 125ms 78ms
trim10 < 0.5ms < 0.5ms
trim11 < 0.5ms < 0.5ms
trim12 < 0.5ms < 0.5ms
补充字符串处理方法集合
补充代码示例:
//String.prototype使用
//批量替换,例如:str.ReplaceAll([/a/g,/b/g,/c/g],["aaa","bbb","ccc"])
String.prototype.ReplaceAll=function (A,B) {
var C=this;
for(var i=0;i<A.length;i++) {
C=C.replace(A[i],B[i]);
};
return C;
};
// 去掉字符两端的空白字符
String.prototype.Trim=function () {
return this.replace(/(^[\t\n\r]*)|([\t\n\r]*$)/g,'');
};
// 去掉字符左边的空白字符
String.prototype.LTrim=function () {
return this.replace(/^[\t\n\r]/g,'');
};
// 去掉字符右边的空白字符
String.prototype.RTrim=function () {
return this.replace(/[\t\n\r]*$/g,'');
};
// 返回字符的长度,一个中文算2个
String.prototype.ChineseLength=function()
{
return this.replace(/[^\x00-\xff]/g,"**").length;
};
// 判断字符串是否以指定的字符串结束
String.prototype.EndsWith=function (A,B) {
var C=this.length;
var D=A.length;
if(D>C)return false;
if(B) {
var E=new RegExp(A+'$','i');
return E.test(this);
}else return (D==0||this.substr(C-D,D)==A);
};
// 判断字符串是否以指定的字符串开始
String.prototype.StartsWith = function(str)
{
return this.substr(0, str.length) == str;
};
// 字符串从哪开始多长字符去掉
String.prototype.Remove=function (A,B) {
var s='';
if(A>0)s=this.substring(0,A);
if(A+B<this.length)s+=this.substring(A+B,this.length);
return s;
};