cSharp中的String.Format方法,是推荐的对字符串进行拼接方法。比如

string hrefFormat = "<a href="\" target="\"_blank\"">{1}</a>";
string hrefHtml = String.Format(hrefFormat, "http://xxx.com", "链接一");
String.Format的第一个参数为格式化的字符串,后面参数为params不定个数、不定类型,根据索引对应标记{0},{1},{2}...
如果参数个数小于标记最大值或标记不以{0}为最小标记,即会抛出错误

当然,除此之外还有对特定数据类型的专用格式化功能。

当前在muselite库中,主要是采用类似cSharp的字符串格式化写法,实现字符串拼接的功能。代码如下:

    if (!String.prototype.format) String.prototype.format = function () {
        if (arguments.length == 0) return this;
        var _ = this, len = arguments.length, i = 0, regExp;
        for (; i < len; i++) {
            regExp = new RegExp('\\{' + i + '\\}', 'g');
            _ = _.replace(regExp, arguments[i].toString());
        }
        len = i = regExp = null;
        return _;
    }

我对format的实现没有什么特别的方法,就是替换。
经过多次对容错、开销等方面的考虑,该方法定型为如上样子。但是该方法还是存在循环,并且每次都将构建一个新的正则对象对整个字符串进行匹配和替换,不是很理想。根据MM同学某次提供的一个正则表达式思路,开始对该方法进行改写。

首先是对所有 {数字} 样的标记进行筛选,并且去除重复和类似 {01} 这样的错误标记。
去除重复标记不是必需的,但是可以减少一些运算,就是替换次数少点。

this.match(/\{0\}|\{[1-9]\d*\}/g)

因为match会返回null,所以我用Array原型方法slice去call一次match的结果。

Array.prototype.slice.call(this.match(/\{0\}|\{[1-9]\d*\}/g), 0)

这样,即使match为null,也会返回一个空的数组,可以继续链写。
下一步将数组排序。因为字符串有可能是“a{1}{0}b{2}b{1}b{0}”,为了下一步去掉重复标记做准备,需要将相同的标记放到一起。

Array.prototype.slice.call(this.match(/\{0\}|\{[1-9]\d*\}/g), 0).sort()

注意这里对排序方式没有要求,我只是为了让相同标记凑到一起。
下面是去除重复,也是最好玩的地方。

Array.prototype.slice.call(this.match(/\{0\}|\{[1-9]\d*\}/g), 0).sort().join('').replace(/(\{\d+\})\1*/g, '$1').match(/\{\d+\}/g))

请重点考虑…replace(/(\{\d+\})\1*/g, ‘$1′)的意思。当然,你可以再slice一次。
然后,测试字符串’a{1}{1}b{02}b{0}b{0}b{15}{1}{15}{15}’,得到结果’{0},{15},{1}’。
到此,我的想要的结果已经都得到了。但是我才注意到,这是个无用的结果,因为它依然与参数没有任何关系。
所以,除了练习了链写和正则,对format的改写失败了,继续用原来的吧。