思想上、实现方式上都有区别,上面那个是吧不要的replace掉,下面那个是把要的replace出来。此外上面那个分两次匹配,下面那个则尝试一次就把结果抽取出来。

解决方案 »

  1.   

    从实现的思想上来看,我认为把不要的替掉会更快,
    从实现的效率上来看,两次分配可能会比一次抽取慢综上,还是认为trim2会快一些:))
      

  2.   

    it seems the two matchings cost dearly
    <script>
    function String.prototype.trim1()
    {
    return this.replace(/^\s+|\s+$/g, "");
    }function String.prototype.trim2()
    {
    return this.replace(/^\s+(.*)\s+$/,"$1");
    }n = 10000;s = " 1234 ";
    alert("***" + s.trim1() + "***");
    alert("***" + s.trim2() + "***");dt = new Date();for (i=0; i < n; i++)
      s.trim1();
    alert(new Date().getTime() - dt.getTime());dt = new Date();for (i=0; i < n; i++)
      s.trim2();
    alert(new Date().getTime() - dt.getTime());
    s = "";
    dt = new Date();for (i=0; i < n; i++)
      s.trim1();
    alert(new Date().getTime() - dt.getTime());dt = new Date();for (i=0; i < n; i++)
      s.trim2();
    alert(new Date().getTime() - dt.getTime());</script>
      

  3.   

    sorry, my trim2() was wrong, check out the following, trim1() is not slower:
    <script>
    function String.prototype.trim1()
    {
    return this.replace(/^\s+|\s+$/g, "");
    }function String.prototype.trim2()
    {
    return this.replace(/^\s*([^\s].*[^\s])\s*$/,"$1");
    }
    n = 10000;s = " 1234 ";
    alert("***" + s.trim1() + "***");
    alert("***" + s.trim2() + "***");dt = new Date();for (i=0; i < n; i++)
      s.trim1();
    alert(new Date().getTime() - dt.getTime());dt = new Date();for (i=0; i < n; i++)
      s.trim2();
    alert(new Date().getTime() - dt.getTime());
    s = "";
    dt = new Date();for (i=0; i < n; i++)
      s.trim1();
    alert(new Date().getTime() - dt.getTime());dt = new Date();for (i=0; i < n; i++)
      s.trim2();
    alert(new Date().getTime() - dt.getTime());</script>
      

  4.   

    跟字符长度有关,如果字符比较长,就要用第二种方法了function String.prototype.trim2()
    {
    return this.replace(/^\s*(.*\S)\s*$/,"$1");
    }
      

  5.   

    感覺一次匹配應該要比兩次匹配快些吧
    還是saucer的方法好,直接測試耗時來判斷bxxxr(我用的是IE5):
    script56.chm里面就有
      

  6.   

    用测试判断,只是用来验证理论,还是先想想为好,而且测试所用数据也不够,
    1.大数据量 s = "  "+new Array(100).join("1234567890")+"  ";
    2.特殊情况 s = "      ",第二种方法就开始错误了继续问,哪个耗时多?
    function String.prototype.trim1()
    {
    return this.replace(/^\s*(.*?)\s*$/,"$1");
    }
    function String.prototype.trim2()
    {
    return this.replace(/^\s*(.*\S?)\s*$/,"$1");
    }
    以及下面的比较
    function String.prototype.trim1()
    {
    return this.replace(/^\s+|\s+$/g, "");
    }function String.prototype.trim2()
    {
    return this.replace(/^\s+/,"").replace(/\s+$/, "");
    }
      

  7.   


    还有下面的又在那个地位呢?<script>
    function String.prototype.trim(){
    var s=this.search(/\S/)
    var e=this.search(/\s*$/)
    return this.substring(s,e)
    }
    s="  "+new Array(100).join("1234567890")+"  ";
    alert("["+s.trim()+"]");
    s="    "
    alert("["+s.trim()+"]");
    s="a    "
    alert("["+s.trim()+"]");
    s="    a"
    alert("["+s.trim()+"]");
    </script>最后还是支持MS提供的第一种方法
      

  8.   

    var s = "sspsspsspsspsspssp"
    用正则怎么把第二个p和第四个p替换成w呢?
      

  9.   

    秋水为何要支持第一种方法,而不是return this.replace(/^\s+/,"").replace(/\s+$/, "");呢?
    我运行下来在大字符串下面后者比前者快一倍,小字符串基本差不多,并且思路是跟前者一致的。那么为何宁愿支持第一种方法?
    (我现在的系统正是使用的后者)
      

  10.   

    这是我的一点资料,献上
    正则表达式是regular expression,看来英文比中文要好理解多了,就是检查表达式符
    不符合规定!!正则表达式有一个功能十分强大而又十分复杂的对象RegExp,在JavaScript1.2 版本以
    上提供。
    下面我们看看有关正则表达式的介绍:
    正则表达式对象用来规范一个规范的表达式(也就是表达式符不符合特定的要求,比如是不是Email
    地址格式等),它具有用来检查给出的字符串是否符合规则的属性和方法。
    除此之外,你用RegExp构造器建立的个别正则表达式对象的属性,就已经预先定义好了正则表达式
    对象的静态属性,你可以随时使用它们。
    核心对象:
    在JavaScript 1.2, NES 3.0以上版本提供。
    在JavaScript 1.3以后版本增加了toSource方法。
    建立方法:
    文字格式或RegExp构造器函数。
    文字建立格式使用以下格式:
    /pattern/flags即/模式/标记构造器函数方法使用方法如下:
    new RegExp("pattern"[, "flags"])即new RegExp("模式"[,"标记"])参数:
    pattern(模式)
    表示正则表达式的文本flags(标记)
    如果指定此项,flags可以是下面值之一:
    g: global match(全定匹配)
    i: ignore case(忽略大小写)
    gi: both global match and ignore case(匹配所有可能的值,也忽略大小写)注意:文本格式中的参数不要使用引号标记,而构造器函数的参数则要使用引号标记。所以下面的
    表达式建立同样的正则表达式:
    /ab+c/i
      new RegExp("ab+c", "i")描述:
    当使用构造函数的时候,必须使用正常的字符串避开规则(在字符串中加入前导字符\ )是必须的。
    例如,下面的两条语句是等价的:
    re = new RegExp("\\w+")
    re = /\w+/下面的提供了在正则表达式中能够使用的完整对特殊字符的一个完整的列表和描述。表1.3:正则表达式中的特殊字符:字符\
    意义:对于字符,通常表示按字面意义,指出接着的字符为特殊字符,\不作解释。
    例如:/b/匹配字符'b',通过在b 前面加一个反斜杠\,也就是/\b/,则该字符变成特殊字符,表示
    匹配一个单词的分界线。
    或者: 
    对于几个字符,通常说明是特殊的,指出紧接着的字符不是特殊的,而应该按字面解释。
    例如:*是一个特殊字符,匹配任意个字符(包括0个字符);例如:/a*/意味匹配0个或多个a。
    为了匹配字面上的*,在a前面加一个反斜杠;例如:/a\*/匹配'a*'。字符^
    意义:表示匹配的字符必须在最前边。
    例如:/^A/不匹配"an A,"中的'A',但匹配"An A."中最前面的'A'。字符$
    意义:与^类似,匹配最末的字符。
    例如:/t$/不匹配"eater"中的't',但匹配"eat"中的't'。字符*
    意义:匹配*前面的字符0次或n次。
    例如:/bo*/匹配"A ghost booooed"中的'boooo'或"A bird warbled"中的'b',但不匹配"A goat g
    runted"中的任何字符。字符+
    意义:匹配+号前面的字符1次或n次。等价于{1,}。
    例如:/a+/匹配"candy"中的'a'和"caaaaaaandy."中的所有'a'。字符?
    意义:匹配?前面的字符0次或1次。
    例如:/e?le?/匹配"angel"中的'el'和"angle."中的'le'。字符.
    意义:(小数点)匹配除换行符外的所有单个的字符。
    例如:/.n/匹配"nay, an apple is on the tree"中的'an'和'on',但不匹配'nay'。
    字符(x)
    意义:匹配'x'并记录匹配的值。
    例如:/(foo)/匹配和记录"foo bar."中的'foo'。匹配子串能被结果数组中的素[1], ..., [n] 返
    回,或被RegExp对象的属性$1, ..., $9返回。字符x|y
    意义:匹配'x'或者'y'。
    例如:/green|red/匹配"green apple"中的'green'和"red apple."中的'red'。字符{n}
    意义:这里的n是一个正整数。匹配前面的n个字符。
    例如:/a{2}/不匹配"candy,"中的'a',但匹配"caandy," 中的所有'a'和"caaandy."中前面的两个
    'a'。字符{n,}
    意义:这里的n是一个正整数。匹配至少n个前面的字符。
    例如:/a{2,}不匹配"candy"中的'a',但匹配"caandy"中的所有'a'和"caaaaaaandy."中的所有'a'字符{n,m}
    意义:这里的n和m都是正整数。匹配至少n个最多m个前面的字符。
    例如:/a{1,3}/不匹配"cndy"中的任何字符,但匹配 "candy,"中的'a',"caandy," 中的前面两个
    'a'和"caaaaaaandy"中前面的三个'a',注意:即使"caaaaaaandy" 中有很多个'a',但只匹配前面的三
    个'a'即"aaa"。字符[xyz]
    意义:一字符列表,匹配列出中的任一字符。你可以通过连字符-指出一个字符范围。
    例如:[abcd]跟[a-c]一样。它们匹配"brisket"中的'b'和"ache"中的'c'。字符[^xyz]
    意义:一字符补集,也就是说,它匹配除了列出的字符外的所有东西。 你可以使用连字符-指出一
    字符范围。
    例如:[^abc]和[^a-c]等价,它们最早匹配"brisket"中的'r'和"chop."中的'h'。字符[\b]
    意义:匹配一个空格(不要与\b混淆)字符\b
    意义:匹配一个单词的分界线,比如一个空格(不要与[\b]混淆)
    例如:/\bn\w/匹配"noonday"中的'no',/\wy\b/匹配"possibly yesterday."中的'ly'。字符\B
    意义:匹配一个单词的非分界线
    例如:/\w\Bn/匹配"noonday"中的'on',/y\B\w/匹配"possibly yesterday."中的'ye'。字符\cX
    意义:这里的X是一个控制字符。匹配一个字符串的控制字符。
    例如:/\cM/匹配一个字符串中的control-M。字符\d
    意义:匹配一个数字,等价于[0-9]。
    例如:/\d/或/[0-9]/匹配"B2 is the suite number."中的'2'。字符\D
    意义:匹配任何的非数字,等价于[^0-9]。
    例如:/\D/或/[^0-9]/匹配"B2 is the suite number."中的'B'。字符\f
    意义:匹配一个表单符字符\n
    意义:匹配一个换行符字符\r
    意义:匹配一个回车符字符\s
    意义:匹配一个单个white空格符,包括空格,tab,form feed,换行符,等价于[ \f\n\r\t\v]。
    例如:/\s\w*/匹配"foo bar."中的' bar'。字符\S
    意义:匹配除white空格符以外的一个单个的字符,等价于[^ \f\n\r\t\v]。
    例如:/\S/\w*匹配"foo bar."中的'foo'。字符\t
    意义:匹配一个制表符字符\v
    意义:匹配一个顶头制表符字符\w
    意义:匹配所有的数字和字母以及下划线,等价于[A-Za-z0-9_]。
    例如:/\w/匹配"apple,"中的'a',"$5.28,"中的'5'和"3D."中的'3'。字符\W 
    意义:匹配除数字、字母外及下划线外的其它字符,等价于[^A-Za-z0-9_]。
    例如:/\W/或者/[^$A-Za-z0-9_]/匹配"50%."中的'%'。字符\n
    意义:这里的n是一个正整数。匹配一个正则表达式的最后一个子串的n的值(计数左圆括号)。例如:/apple(,)\sorange\1/匹配"apple, orange, cherry, peach."中的'apple, orange',下面
    有一个更加完整的例子。
    注意:如果左圆括号中的数字比\n指定的数字还小,则\n取下一行的八进制escape作为描述。字符\ooctal和\xhex
    意义:这里的\ooctal是一个八进制的escape值,而\xhex是一个十六进制的escape值,允许在一个
    正则表达式中嵌入ASCII码。
    当表达式被检查的时候,文字符号提供了编辑正则表达式的方法。利用文字符号可以使到正则表达
    式保持为常数。例如,如果你在一个循环中使用文字符号来构造一个正则表达式,正则表达式不需进行
    反复编译。
    正则表达式对象构造器,例如,new RegExp("ab+c"),提供正则表达式的运行时编译。当你知道正
    则表达式的模式会变化的时候,应该使用构造函数,或者你不知道正则表达式的模式,而它们是从另外
    的源获得的时候,比如由用户输入时。一旦你定义好了正则表达式,该正则表达式可在任何地方使用,
    并且可以改变,你可以使用编译方法来编译一个新的正则表达式以便重新使用。
    一个分离预先定义的RegExp对象可以在每个窗口中使用;也就是说,每个分离的JavaScript线程运
    行以获得自己的RegExp对象。因为每个脚本在一个线程中是不可中断的,这就确保了不同的脚本不会覆
    盖RegExp对象的值。
    预定义的RegExp对象包含的静态属性:input, multiline, lastMatch,lastParen, leftContext, 
    rightContext, 以及从$1到$9。input和multiline属性能被预设。其它静态属性的值是在执行个别正则
    表达式对象的exec和test方法后,且在执行字符串的match和replace方法后设置的。属性
    注意RegExp对象的几个属性既有长名字又有短名字(象Perl)。这些名字都是指向相同的值。Perl是
    一种编程语言,而JavaScript模仿了它的正则表达式。属性$1, ..., $9
    取得匹配的子串,如果有的话属性$_
    参考input属性$*
    参考multiline属性$&
    参考lastMatch属性$+
    参考lastParen属性$`
    参考leftContext属性$'
    参考rightContext属性constructor
    指定用来建立对象原型函属性global
    决定是否测试正则表达式是否不能匹配所有的字符串,或者只是与最先的冲突。属性ignoreCase
    决定试图匹配字符串的时候是否忽略大小写属性input
    当正则表达式被匹配的时候,为相反的字符串。属性lastIndex
    决定下一次匹配从那里开始属性lastMatch
    最后一个匹配的字符属性lastParen
    子串匹配的时候,最后一个parenthesized,如果有的话。属性leftContext
    最近一次匹配前的子串。属性multiline
    是否在串的多行中搜索。属性prototype
    允许附加属性到所有的对象属性rightContext
    最近一次匹配后的的子串。属性source
    模式文本方法
    compile方法
    编译一个正则表达式对象exec方法
    运行正则表达式匹配test方法
    测试正则达式匹配toSource方法
    返回一个对象的文字描述指定的对象;你可以使用这个值来建立一个新的对象。不考虑Object.toS
    ource方法。toString方法
    返回一个字符串描述指定的对象,不考虑Object.toString对象。valueOf方法
    返回指定对角的原始值。不考虑Object.valueOf方法。 另外,这个对象继承了对象的watch和unwatch方法
      例子:
      例1、下述示例脚本使用replace方法来转换串中的单词。在替
      

  11.   

    测试一下,到底谁会胜出呢?<SCRIPT LANGUAGE="JavaScript">
    <!--
    function String.prototype.trim1()
    {
    return this.replace(/(^\s*)|(\s*$)/g, "");
    }
    function String.prototype.trim2()
    {
    return this.replace(/^\s*(.*\S?)\s*$/,"$1");
    }
    function String.prototype.trim3()
    {
    return this.replace(/^\s+|\s+$/g, "");
    }function String.prototype.trim4()
    {
    return this.replace(/^\s+/,"").replace(/\s+$/, "");
    }function test(st,n){
    "".trim1();"".trim2();"".trim3();"".trim4(); var td = new Date();
    for (var i=0;i<n;i++) st.trim1();
    var t1 = new Date()-td; td = new Date();
    for (var i=0;i<n;i++) st.trim2();
    var t2 = new Date()-td; td = new Date();
    for (var i=0;i<n;i++) st.trim3();
    var t3 = new Date()-td; td = new Date();
    for (var i=0;i<n;i++) st.trim4();
    var t4 = new Date()-td; return [t1,t2,t3,t4];
    }document.write("<table cellpadding=5><tr><td>trim1</td><td>trim2</td><td>trim3</td><td>trim4</td></tr>")var n=9000var st = "";
    var t = test(st,n);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;var st = "    ";
    var t = test(st,n);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;var st = "abc";
    var t = test(st,n);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;var st = "   abc";
    var t = test(st,n);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;var st = "abc   ";
    var t = test(st,n);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;var st = "    abc    ";
    var t = test(st,n);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;var st = s = "  "+new Array(100).join("1234567890")+"  ";
    var t = test(st,n/3);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;var st = s = new Array(100).join("       ")+new Array(100).join("abcdefa")+new Array(100).join("       ");
    var t = test(st,n/3);
    document.write("<tr><td>"+t[0]+"</td><td>"+t[1]+"</td><td>"+t[2]+"</td><td>"+t[3]+"</td></tr>");;document.write("</table>")//-->
    </SCRIPT>
      

  12.   

    >>>>var s = "sspsspsspsspsspssp"
    >>>>用正则怎么把第二个p和第四个p替换成w呢?<script>
    var re = /^([^p]*)(p)([^p]*)(\2)([^p]*)(\2)([^p]*)(\2)(.*)$/;
    var rp = "$1$2$3w$5$6$7w$9";
    var s = "sspsspsspsspsspssp";
    alert(s)
    s=s.replace(re,rp);
    alert(s);
    var s = "pppp";
    alert(s)
    s=s.replace(re,rp);
    alert(s);
    </script>
      

  13.   

    不行,
    function String.prototype.trim2()
    {
    return this.replace(/^\s*(.*\S?)\s*$/,"$1");
    }虽然快,可是有错,因为中间的.*会贪心的把后面的空格给吃进来呀。该怎么写呢?return this.replace(/^\s*(.*\S)\s*$/,"$1");这样又对付不了空串。
      

  14.   

    >>>>这样又对付不了空串
    why do you need to worry about 空串? if the expression doesn't match, the replacement never occurs if you insist, try (some lower version IEs may not support .*?)function String.prototype.trim2()
    {
    return this.replace(/^\s*(.*?\S?)\s*$/,"$1");
    }
      

  15.   

    IE5.5+用,callback趋势
    <script>
    function pw(str){
    var i=0;
    return str.replace(/p/g,function (){return i++%2?"w":"p"})
    }
    alert(pw("sspsspsspsspsspssp"))
    alert(pw("pppp"))
    </script>
      

  16.   

    问题是:第二个正则表达式不正确!!!!
    var test="     ";
    alert("\""+test.trim2()+"\"");
      

  17.   

    function String.prototype.trim2()
    {
    return this.replace(/(^\s*(.*\S)\s*$|^\s*$)/,"$2");
    }这样速度上就没有很大优势了。
      

  18.   

    换一个思路,可以这么写:
    return this.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/,"$1");速度也不慢。(ie5.5以前的版本将?:去掉,但是速度会有所下降)
      

  19.   

    的确跟长度有关,我在php用长一点(不是楼主所说的正则)的测600个文件用了4200s,用小一点的用了3000s.
    当然这里面有出入,但是大致是这样的
      

  20.   

    4200s?应该是4200ms吧?不然要一个多小时了