`

如何摆脱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中判断某个字符串是否包含另一个字符串的五种方法

    indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。如果要检索的字符串值没有出现,则该方法返回 -1。 方法二:match() var str = "123" var reg = RegExp(/3/); if(str.match(reg)){ //包含; } ...

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

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

    字符串排序方法

    #### 描述:字符串排序方法——在JavaScript中的字符串排序技巧。 #### 标签:JS #### 部分内容解析: 虽然提供的代码示例是用Java编写的,但我们可以从中提取出排序的核心思想,并将其应用到JavaScript中。 ### ...

    js页面字符串转json对象

    js页面字符串转json对象

    javaScript中的字符串操作

    ### JavaScript中的字符串操作知识点 #### 一、概述 在JavaScript编程中,字符串处理是一项非常基础且重要的技能。无论是用户输入的验证、DOM元素属性的读取与修改、还是Cookie的操作等场景,都离不开字符串的使用...

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

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

    js截取字符串-三种方法

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

    js替换字符串

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

    连接 字符 串.rar

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

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

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

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

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

    js字符串操作大全

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

    JavaScript代码判断输入的字符串是否含有特殊字符和表情代码实例

    标题中所提及的“JavaScript代码判断输入的字符串是否含有特殊字符和表情”,实质上是介绍了一种使用JavaScript语言进行前端数据验证的技术方法。这种技术常见于各种表单验证中,用于确保用户输入的数据符合特定格式...

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

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

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

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

    截取指定长度的字符串

    在实际编程中,可以根据具体需求选择合适的方法,并结合其他字符串操作,如查找、替换、连接等,以实现更复杂的字符串处理任务。记住,实践是检验理解的最佳方式,所以尝试编写一些代码来练习这个概念吧!

    js string转date(js字符串转换成日期,代码调试通)

    js string转date,js字符串转换成日期,此代码支持将datetime(年月日小时分秒格式)转换为js的Date类型,程序已调试并支持在HTML中运行、代码请见附件。

Global site tag (gtag.js) - Google Analytics