你必须知道的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 相关文章推荐
使用jQuery的ajax功能实现的RSS Reader 代码
Sep 03 Javascript
jquery新的绑定事件机制on方法的使用方法
Apr 15 Javascript
获取中文字符串的实际长度代码
Jun 05 Javascript
JS实现的仿淘宝交易倒计时效果
Nov 27 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
Aug 26 Javascript
JavaScript实现无穷滚动加载数据
May 06 Javascript
详谈构造函数加括号与不加括号的区别
Oct 26 Javascript
jQuery图片查看插件Magnify开发详解
Dec 25 jQuery
JavaScript DOM元素常见操作详解【添加、删除、修改等】
May 09 Javascript
JavaScript 判断iPhone X Series机型的方法
Jan 28 Javascript
微信小程序获取复选框全选反选选中的值(实例代码)
Dec 17 Javascript
让Vue响应Map或Set的变化操作
Nov 11 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
php读取mysql中文数据出现乱码的解决方法
2013/08/16 PHP
PHP5.3安装Zend Guard Loader图文教程
2014/09/29 PHP
PHP的自定义模板引擎
2017/03/24 PHP
thinkPHP+phpexcel实现excel报表输出功能示例
2017/06/06 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
我见过最全的个人js加解密功能页面
2007/12/12 Javascript
javascript面向对象编程(一) 实例代码
2010/06/25 Javascript
基于JQuery 的消息提示框效果代码
2011/07/31 Javascript
ExtJS如何设置与获取radio控件的选取状态
2014/01/22 Javascript
javascript使用正则获取url上的某个参数
2014/09/04 Javascript
javascript函数声明和函数表达式区别分析
2014/12/02 Javascript
JS随机调用指定函数的方法
2015/07/01 Javascript
关于获取DIV内部内容报错的原因分析及解决办法
2016/01/29 Javascript
JS组件系列之Bootstrap table表格组件神器【二、父子表和行列调序】
2016/05/10 Javascript
JSONP跨域请求实例详解
2016/07/04 Javascript
Three.js学习之正交投影照相机
2016/08/01 Javascript
jQuery源码分析之sizzle选择器详解
2017/02/13 Javascript
微信小程序页面开发注意事项整理
2017/05/18 Javascript
初探JavaScript 面向对象(推荐)
2017/09/03 Javascript
JavaScript实现开关等效果
2017/09/08 Javascript
详解Vue源码学习之双向绑定
2019/04/10 Javascript
详解关闭令人抓狂的ESlint 语法检测配置方法
2019/10/28 Javascript
JS实现排行榜文字向上滚动轮播效果
2019/11/26 Javascript
vue项目中使用particles实现粒子背景效果及遇到的坑(按钮没有点击响应)
2020/02/11 Javascript
如何实现echarts markline标签名显示自己想要的
2020/07/20 Javascript
基于VSCode调试网页JavaScript代码过程详解
2020/07/20 Javascript
JS如何生成动态列表
2020/09/22 Javascript
python 切片和range()用法说明
2013/03/24 Python
Python实现登录人人网并抓取新鲜事的方法
2015/05/11 Python
django的登录注册系统的示例代码
2018/05/14 Python
Python paramiko模块使用解析(实现ssh)
2019/08/30 Python
python 制作python包,封装成可用模块教程
2020/07/13 Python
公司合作协议书范本
2014/04/18 职场文书
城管综合整治方案
2014/05/01 职场文书
令人印象深刻的自荐信
2014/05/25 职场文书
关于运动会的广播稿(10篇)
2014/09/12 职场文书