你必须知道的JavaScript 中字符串连接的性能的一些问题


Posted in Javascript onMay 07, 2013

而JavaScript的核心是ECMAScript 。与其他语言类似,ECMAScript 的字符串是不可变的,即它们的值不能改变。

请考虑下面的代码:

var str = "hello ";
str += "world";实际上,这段代码在幕后执行的步骤如下:

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

每次完成字符串连接都会执行步骤 2 到 6,使得这种操作非常消耗资源。如果重复这一过程几百次,甚至几千次,就会造成性能问题。解决方法是用 Array 对象存储字符串,然后用 join() 方法(参数是空字符串)创建最后的字符串。想象用下面的代码代替前面的代码:

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

这样,无论数组中引入多少字符串都不成问题,因为只在调用 join() 方法时才会发生连接操作。此时,执行的步骤如下:

1.创建存储结果的字符串
2.把每个字符串复制到结果中的合适位置
虽然这种解决方案很好,但还有更好的方法。问题是,这段代码不能确切反映出它的意图。要使它更容易理解,可以用 StringBuffer 类打包该功能:

function StringBuffer () {
  this._strings_ = new Array();
}
StringBuffer.prototype.append = function(str) {
  this._strings_.push(str);
};
StringBuffer.prototype.toString = function() {
  return this._strings_.join("");
};

这段代码首先要注意的是 strings 属性,本意是私有属性。它只有两个方法,即 append() 和 toString() 方法。append() 方法有一个参数,它把该参数附加到字符串数组中,toString() 方法调用数组的 join 方法,返回真正连接成的字符串。要用 StringBuffer 对象连接一组字符串,可以用下面的代码:
var buffer = new StringBuffer ();
buffer.append("hello ");
buffer.append("world");
var result = buffer.toString();

基于上面的实现我们来进行一下运行时间对比,即以“+”逐个进行字符串连接和我们封装的工具。可用下面的代码测试 StringBuffer 对象和传统的字符串连接方法的性能,在chrome控制台输入一下代码并运行:
var d1 = new Date();
var str = "";
for (var i=0; i < 10000; i++) {
    str += "text";
}
var d2 = new Date();
console.log("Concatenation with plus: "
 + (d2.getTime() - d1.getTime()) + " milliseconds");
var buffer = new StringBuffer();
d1 = new Date();
for (var i=0; i < 10000; i++) {
    buffer.append("text");
}
var result = buffer.toString();
d2 = new Date();
console.log("Concatenation with StringBuffer: "
 + (d2.getTime() - d1.getTime()) + " milliseconds");

这段代码对字符串连接进行两个测试,第一个使用加号,第二个使用 StringBuffer 类。每个操作都连接 10000 个字符串。日期值 d1 和 d2 用于判断完成操作需要的时间。请注意,创建 Date 对象时,如果没有参数,赋予对象的是当前的日期和时间。要计算连接操作历经多少时间,把日期的毫秒表示(用 getTime() 方法的返回值)相减即可。这是衡量 JavaScript 性能的常见方法。该测试的结果可以帮助您比较使用 StringBuffer 类与使用加号的效率差异。

上例运行结果如下:

你必须知道的JavaScript 中字符串连接的性能的一些问题

那么有人也许会说JavaScript的String对象中不是也封装一个concat()方法么,我们在下面也来用concat()方法来做同样的事情,在consoel输入以下代码:

var d1 = new Date();
var str = "";
for (var i=0; i < 10000; i++) {
    str.concat("text");
}
var d2 = new Date();
console.log("Concatenation with plus: "
 + (d2.getTime() - d1.getTime()) + " milliseconds");

我们可以看到做10000次字符窜连接它的耗时是:

你必须知道的JavaScript 中字符串连接的性能的一些问题

由此可以得出结论,当涉及到一定数量的字符串连接时,我们在Javascript中封装一个类似Java中的StringBuffer对象(函数)来进行操作会在性能上得到提升。

Javascript 相关文章推荐
Javascript 个人笔记(没有整理,很乱)
Jul 07 Javascript
超强的IE背景图片闪烁(抖动)的解决办法
Sep 09 Javascript
JavaScript 工具库 Cloudgamer JavaScript Library v0.1 发布
Oct 29 Javascript
jQuery的animate函数学习记录
Aug 08 Javascript
基于javascript简单实现对身份证校验
Jan 25 Javascript
JS取数字小数点后两位或n位的简单方法
Oct 24 Javascript
js仿新浪微博消息发布功能
Feb 17 Javascript
前端开发之CSS原理详解
Mar 11 Javascript
js Date()日期函数浏览器兼容问题解决方法
Sep 12 Javascript
微信小程序之swiper轮播图中的图片自适应高度的方法
Apr 23 Javascript
node前端模板引擎Jade之标签的基本写法
May 11 Javascript
详解SPA中前端路由基本原理与实现方式
Sep 12 Javascript
基于JavaScript实现继承机制之构造函数方法对象冒充的使用详解
May 07 #Javascript
基于JavaScript实现继承机制之调用call()与apply()的方法详解
May 07 #Javascript
JS中的substring和substr函数的区别说明
May 07 #Javascript
js图片自动切换效果处理代码
May 07 #Javascript
JavaScript通过RegExp实现客户端验证处理程序
May 07 #Javascript
JS注册/移除事件处理程序(ExtJS应用程序设计实战)
May 07 #Javascript
使用Math.floor与Math.random取随机整数的方法详解
May 07 #Javascript
You might like
JS实现php的伪分页
2008/05/25 PHP
解析如何在PHP下载文件名中解决乱码的问题
2013/06/20 PHP
PHP FATAL ERROR: CALL TO UNDEFINED FUNCTION BCMUL()解决办法
2014/05/04 PHP
PDO的安全处理与事物处理方法
2016/10/31 PHP
基于PHP常用文件函数和目录函数整理
2017/08/17 PHP
PHP使用Redis实现防止大并发下二次写入的方法
2017/10/09 PHP
跟我一起学写jQuery插件开发方法(附完整实例及下载)
2010/04/01 Javascript
JavaScript实现自己的DOM选择器原理及代码
2013/03/04 Javascript
解决Extjs4中form表单提交后无法进入success函数问题
2013/11/26 Javascript
jQuery学习笔记之jQuery构建函数的7种方法
2014/06/03 Javascript
jQuery中prevAll()方法用法实例
2015/01/08 Javascript
javascript实现下班倒计时效果的方法(可桌面通知)
2015/07/10 Javascript
domReady的实现案例
2016/11/23 Javascript
JavaScript函数绑定用法实例分析
2017/11/14 Javascript
JS实现简易换图时钟功能分析
2018/01/04 Javascript
VUE DOM加载后执行自定义事件的方法
2018/09/07 Javascript
微信小程序textarea层级过高的解决方法
2019/03/04 Javascript
详解JavaScript中关于this指向的4种情况
2019/04/18 Javascript
详解element-ui级联菜单(城市三级联动菜单)和回显问题
2019/10/02 Javascript
VUE table表格动态添加一列数据,新增的这些数据不可以编辑(v-model绑定的数据不能实时更新)
2020/04/03 Javascript
NodeJS多种创建WebSocket监听的方式(三种)
2020/06/04 NodeJs
Vue+penlayers实现多边形绘制及展示
2020/12/24 Vue.js
[55:11]完美世界DOTA2联赛PWL S2 SZ vs LBZS 第一场 11.26
2020/11/30 DOTA
Python+matplotlib+numpy绘制精美的条形统计图
2018/01/02 Python
对python实现二维函数高次拟合的示例详解
2018/12/29 Python
浅谈Python类中的self到底是干啥的
2019/11/11 Python
CSS3 实现弹幕的示例代码
2017/08/07 HTML / CSS
英国玛莎百货澳大利亚:Marks & Spencer Australia
2019/08/30 全球购物
下列程序在32位linux或unix中的结果是什么
2015/01/26 面试题
什么是用户模式(User Mode)与内核模式(Kernel Mode) ?
2014/07/21 面试题
Unix如何在一行中运行多个命令
2015/05/29 面试题
业务助理岗位职责
2013/11/18 职场文书
两年的个人工作自我评价
2014/01/10 职场文书
跳蚤市场口号
2014/06/13 职场文书
督导岗位职责范本
2015/04/10 职场文书
Mysql分析设计表主键为何不用uuid
2022/03/31 MySQL