`

如何摆脱JS糟糕的字符串连接,我掉进了陷阱

阅读更多

一、ECMAScript的字符串是不可变的,即它们的值不能改变,因此当你写出下面的代码的时候发生了什么呢?

var str = "Hello ";
str += "world";

 执行的步骤如下:

  1. 创建存储“Hello“的字符串
  2. 创建存储”world“的字符串
  3. 创建存储连接结果的字符串
  4. 把str的当前内容复制到结果中
  5. 把“world”复制到结果中
  6. 更新str,使它指向结果

    每次完成字符串的连接都会执行步骤2-6,使得这种操作非常消耗资源。想象一下重复这个过程几百次,甚至几千次,那性能如何?

 

二、那么再看看下面的代码,来解决这种窘况

var arr = new Array;
arr[0] = "Hello ";
arr[1] = "world";
var str = arr.join(""); 

执行的步骤如下:

  1. 创建存储结果的字符串
  2. 把每个字符串复制到结果中的适当位置

这样,无论数组要引入多少字符串都不成问题,因为只有在调用join()方法时候才会发生连接操作。

 

三、觉得操作很复杂?代码不能确切反应它的意图?那么我们用对象的解决方式吧,使它更容易理解,用StringBuffer类来封装该功能:

function StringBuffer() {
    this._strs = new Array;
}

StringBuffer.prototype.append = function (str) {
    this._strs.push(str);
};

StringBuffer.prototype.toString = function() {
    this._strs.join("");
};

    好了,感受一下吧,现在如何操作字符串呢?

var sb = new StringBuffer();
sb.append("Hello ");
sb.append("world");
var result = sb.toString();

 

四、似乎色香味俱全了,但是吃下去的功效如何?

var tStart = new Date();
var str = "";
for(var i=0;i<10000;i++)
{
   str += "text"
}
var tEnd = new Date();

document.write("原始的方法加号 拼接10000个字符串 花费时间:"+(tEnd.getTime()-tStart.getTime())+"秒");


var oSB = new StringBuffer();
tStart = new Date();
for(var i=0;i<10000;i++)
{
    oSB.append("text");
}
var sRst = oSB.toString();
tEnd = new Date();

document.write("<br/>StringBuffer 拼接10000个字符串 花费时间:"+(tEnd.getTime()-tStart.getTime())+"秒");

 

   可能你已经猜到了,StringBuffer要比+快,到底快多少呢?我的测试结果:

 

 

FF3.0.10
原始的方法加号 拼接10000个字符串 花费时间:3豪秒
StringBuffer 拼接10000个字符串 花费时间:8豪秒 

IE7
原始的方法加号 拼接10000个字符串 花费时间:15豪秒
StringBuffer 拼接10000个字符串 花费时间:16豪秒 

IE8
原始的方法加号 拼接10000个字符串 花费时间:15豪秒
StringBuffer 拼接10000个字符串 花费时间:16豪秒

Chrome1.0.154.46
原始的方法加号 拼接10000个字符串 花费时间:1豪秒
StringBuffer 拼接10000个字符串 花费时间:2豪秒

 

五、怎么回事?

 

    恩?眼睛花了?还是测试结果贴错了?还是……?

 

    一切都没有错!

 

    2006年11月此书出版《JavaScript高级程序设计》在84-85页,就是我上面的内容,我的测试结果却和它的完全相反,技术的变革还是……?

 

    我觉得是一个教训!深刻的教训!不知道哪看了这篇文章的人会有何感想。

 

12
3
分享到:
评论
16 楼 ydqwtt 2012-09-12  
我测试也出现这种情况了,StringBuffer的效率没有+连接字符的效率高呢,有谁知道连接字符串用哪种效率最高啊,在JS中
15 楼 night_stalker 2009-05-06  
还是比较喜欢下面这样的写法(prototype):
buf = []
(10000).times(function(){buf.push("text")})
buf.join("")
14 楼 hax 2009-05-06  
IE6下字符串拼接慢不是因为字符串创建的关系,而是因为白痴的垃圾回收算法。
13 楼 elf8848 2009-05-06  
引用
果然是抱着怀疑一切的态度在看书

果然是抱着怀疑一切的态度在看书
12 楼 jessdy 2009-05-06  
IE6
原始的方法加号 拼接10000个字符串 花费时间:516秒
StringBuffer 拼接10000个字符串 花费时间:78秒
Array 拼接10000个字符串 花费时间:47秒
第三种
var oa = [];
tStart = new Date();
for(var i=0;i<10000;i++)
{
    oa.push("text");
}
var oRst = oa.join("");
tEnd = new Date();
document.write("<br/>Array 拼接10000个字符串 花费时间:"+(tEnd.getTime()-tStart.getTime())+"秒");

11 楼 jessdy 2009-05-06  
IE 6
原始的方法加号 拼接10000个字符串 花费时间:453秒
StringBuffer 拼接10000个字符串 花费时间:79秒

CHROME
原始的方法加号 拼接10000个字符串 花费时间:1秒
StringBuffer 拼接10000个字符串 花费时间:4秒
10 楼 block 2009-05-05  
IE6测试结果:
原始的方法加号 拼接10000个字符串 花费时间:157秒
StringBuffer 拼接10000个字符串 花费时间:78秒
9 楼 qamer 2009-05-05  
果然是抱着怀疑一切的态度在看书
8 楼 jianyi.hh 2009-05-04  
new StringBuffer();  换成 []
append换成 push
toString 换成 join("")
再试试。
FF下 我测试得结果:
                  原始的方法加号 拼接10000个字符串 花费时间:15秒
                  数组拼接10000个字符串 花费时间:14秒
7 楼 kaipingk 2009-05-04  
kaipingk 写道

js 里面叶有 StringBuffer?

不好意思,看漏了
6 楼 kaipingk 2009-05-04  
js 里面叶有 StringBuffer?
5 楼 mating 2009-05-03  
是吗?不是一直说StringBuffer快吗!难道效率没+高!不会吧!我记得上次javaEye还有个人发个帖子说数据量大的话还是用StringBuffer啊!
4 楼 cloudgamer 2009-05-03  
不说还真不知道
不过也正常,原作者写的时候距今估计也好几年了
当年的“高级”现在也已经成了入门了
3 楼 iammonster 2009-05-03  
呵呵,5.1有点时间,把经常用的东西,翻了翻
2 楼 wh8766 2009-05-03  
楼主的研究精神值得学习 赞下
1 楼 playfish 2009-05-02  

呵呵,因为书出得比较早的关系吧.06年的时候,主要的浏览器是IE6跟FF2.

如果你拿到IE6下面去测试,你就会真正发现问题.

IE6执行字符串拼接的实现,是错误的,注意,是错误,而不仅仅是bug.这导致IE6在执行字符串操作时候的效率极其低下.而我们通常谈的js性能优化,大部分其实都是在对IE6做优化.


你看书看起来还是挺认真的嘛,呵呵.

相关推荐

    JS去掉字符串空格

    在JavaScript(简称JS)开发中,对字符串进行操作是一项常见且重要的任务,其中去除字符串中的空格是一个典型的处理需求。本文将深入探讨如何利用JS来有效地去除字符串中的空格,包括单个空格、多个连续空格以及字符...

    javascript实现的字符串与十六进制表示字符串相互转换方法

    本文实例讲述了javascript实现的字符串与十六进制表示字符串相互转换方法。分享给大家供大家参考。具体如下: 之所以写这个,是因为发现SQL注入和XSS中经常利用十六进制表示的字符串,比如 SELECT CONCAT(0x68656c6...

    js以逗号分隔方式添加删除字符串

    在JavaScript(JS)中,处理字符串是常见的编程任务之一,特别是在构建动态网页和应用程序时。本文将深入探讨如何以逗号或其他自定义分隔符来添加或删除字符串,并且会强调不支持正则表达式中的特殊字符。我们将通过...

    头歌教学实践平台 Web前端开发基础 JavaScript学习手册九:字符串

    2. 连接字符串:可以使用`+`运算符或`concat()`方法连接字符串。 3. 字符串切割:`slice()`, `substring()`, `substr()`用于截取字符串,`split()`根据分隔符切割成数组。 4. 查找替换:`indexOf()`查找指定子串首次...

    js页面字符串转json对象

    js页面字符串转json对象

    JavaScript判断一个字符串是否包含指定子字符串的方法

    JavaScript是一种广泛使用的前端脚本语言,它为我们提供了丰富的API,能够操作DOM、处理事件、操作字符串等。在处理字符串时,判断一个字符串是否包含另一个子字符串是常见的需求。本篇内容将详细介绍如何使用...

    js替换字符串

    ### JavaScript字符串替换技术详解 在Web开发中,JavaScript(简称JS)作为一种强大的客户端脚本语言,在处理DOM元素、样式及动态交互方面具有不可替代的作用。本文将深入探讨JS中的字符串替换功能及其应用案例,...

    连接 字符 串.rar

    - **JavaScript**:JavaScript的`+`运算符同样适用于字符串连接,另外还有模板字符串(`模板字面量`)的方式,用反引号(``)包裹,支持嵌入表达式 `${}`。 - **C/C++**:C和C++中没有内置的字符串连接函数,通常...

    易语言八种方法倒转字符串源码

    在易语言编程环境中,倒转字符串是一个常见的操作,可以用于各种文本处理任务。本文将详细介绍八种不同的方法来实现这一功能,并提供相应的源码。易语言作为一款中文编程语言,以其简洁直观的语法深受初学者和专业...

    js分割字符串 js分割字符串 js分割字符串

    JavaScript中的字符串分割是一个重要的操作,尤其在处理用户输入或数据解析时。本文将详细探讨JavaScript中六种不同的字符串分割方法,以及它们各自的特点和应用场景。 1. `slice(start, end)`: `slice()`方法从...

    以太坊solidity字符串拼接实现

    不过,在Solidity编程语言中,由于其特定的类型系统和内存管理机制,没有像其他高级编程语言(如JavaScript或Python)中那样直接支持字符串拼接运算符。因此,开发者需要了解如何在Solidity中实现字符串拼接,这通常...

    js中的json对象和字符串之间的转化

    2. **字符串与JSON对象之间的转化**:JavaScript提供了两个内置函数来实现这种转化:`JSON.stringify()`用于将JavaScript对象转换为JSON字符串,`JSON.parse()`用于将JSON字符串转换回JavaScript对象。 **描述中的...

    js截取字符串-三种方法

    JavaScript中的字符串截取是编程中常见的操作,主要涉及到三个方法:`slice()`、`substr()` 和 `substring()`。这三个方法都是用来从一个字符串中提取一部分新的字符串,但它们的使用方式和逻辑略有不同。 首先,...

    js判断输入字符串是否为空、空格、null的方法总结

    判断字符串是否为空 var strings = ''; if (string.length == 0) { alert&#40;'不能为空'&#41;; } 判断字符串是否为“空”字符即用户输入了空格 var strings = ' '; if (strings.replace(/(^s*)|(s*$)/g, )....

    JS字符串false转boolean的方法(推荐)

    在JavaScript中,将字符串"false"转换为布尔值false并不是一个简单的隐式转换,因为JavaScript会把字符串"false"视作一个真值。针对这个特定问题,我们需要一个明确的方法来确保字符串"false"能被正确转换成布尔的...

    js对中文字符串进行gb2312编码解码

    在JavaScript(JS)中,处理中文字符编码是一个常见的需求,特别是在与服务器交互或者处理文本数据时。GB2312编码是一种在中国大陆广泛使用的简体中文字符集,它包含了6763个常用汉字和一些其他字符。在JavaScript中...

    js字符串操作大全

    根据给定的文件信息,我们将深入探讨JavaScript(简称JS)中的字符串操作,这些操作对于处理文本数据至关重要。本文将详细解析文件中提到的部分扩展方法,包括去除字符串两侧空格、获取字符串的左侧、右侧或中间部分...

    再论Javascript下字符串连接的性能

    在JavaScript中,字符串连接是常见的操作,特别是在处理大量文本数据时。本文主要探讨了两种主要的字符串连接方法:使用字符串连接运算符和使用数组。这两种方法在不同情况下有不同的性能表现,尤其是在不同的浏览器...

    JavaScript中判断两个字符串是否相等的方法

    在JavaScript中判断两个字符串是否相等是编程基础中的重要内容,尤其对于初学者来说,理解字符串相等性的判断方法对于编写有效的代码至关重要。首先,要了解JavaScript提供了两种相等性运算符:“==”和“===”。这...

Global site tag (gtag.js) - Google Analytics