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

而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的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中封装一个类似Java中的StringBuffer对象(函数)来进行操作会在性能上得到提升。

(0)

相关推荐

  • JS 字符串连接[性能比较]

    一.ECMAScript的字符串是不可变的,即它们的值不能改变,因此当你写出下面的代码的时候发生了什么呢? Js代码 复制代码 代码如下: var str = "Hello "; str += "world"; 执行的步骤如下: 创建存储"Hello"的字符串 创建存储"world"的字符串 创建存储连接结果的字符串 把str的当前内容复制到结果中 把"world"复制到结果中 更新str,使它指向结果 每

  • javascript下高性能字符串连接StringBuffer类

    复制代码 代码如下: function StringBuffer(){ this.__strings__ = new Array(); } StringBuffer.prototype.append = function(str){ this.__strings__.push(str); }; StringBuffer.prototype.toString = function(){ this.__strings__.join(" "); }; 其实上面的代码,主要利用了js的数组原理

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

    1 如何进行字符串连接? 首先让我们来回顾一下字符串连接的两种常用方法: 1.1 使用字符串连接运算符 常用的语言(如Java.C#.PHP等)都有字符串连接运算符,Javascript也不例外,代码示例: 复制代码 代码如下: var str = ""; str = str + "a"; 1.2 使用数组 在常用的语言中,字符串连接运算的性能普遍不高,为此在C#中就专门提供了StringBuilder(Java中提供了StringBuffer)用于连接字符串.而在

  • 浅谈JS中的三种字符串连接方式及其性能比较

    工作中经常会碰到要把2个或多个字符串连接成一个字符串的问题,在JS中处理这类问题一般有三种方法,这里将它们一一列出顺便也对它们的性能做个具体的比较. 第一种方法 用连接符"+"把要连接的字符串连起来: str="a"; str+="b"; 毫无疑问,这种方法是最便捷快速的,如果只连接100个以下的字符串建议用这种方法最方便. 第二种方法 以数组作为中介用 join 连接字符串: var arr=new Array(); arr.push(a);

  • 数组方法解决JS字符串连接性能问题有争议

    1.传统上,字符串连接一直是js中性能最低的操作之一. var text="Hello"; text+=" World!"; 早期浏览器没有对这种运算进行优化. 由于字符串是不可变的,这意味着要创建中间字符串来存储连接的结果.频繁地在后台创建和销毁字符串导制性能异常低下. 2.发现这一点后,开发者们利用数组对象进行优化. var buffer=[],i=0; buffer[i++]="Hello";//通过相应索引值添加元素比push方法快 bu

  • 温故知新——JavaScript中的字符串连接问题最全总结(推荐)

    ECMAScript 中最常见的一个问题是字符串连接的性能.与其他语言类似,ECMAScript 的字符串是不可变的,即它们的值不能改变.请考虑下面的代码: var str = "hello "; str += "world"; 实际上,这段代码在幕后执行的步骤如下: 1.创建存储 "hello " 的字符串. 2.创建存储 "world" 的字符串. 3.创建存储连接结果的字符串. 4.把 str 的当前内容复制到结果中.

  • javascript 字符串连接的性能问题(多浏览器)

    书中附带的测试代码如下  复制代码 代码如下: <html> <head> <title>Example</title> </head> <body> <p><strong>Note:</strong> The latest versions of Firefox seem to have fixed the string concatenation problem. If you are usin

  • JavaScript 字符串连接性能优化

    复制代码 代码如下: var str = "hello"; str += " world"; 后台所做工作: 1)创建存储 "hello" 的字符串,且使 str 指向它. 2)创建存储 "world" 的字符串. 3)创建存储结果的字符串. 4)将 str 中的当前内容复制到结果字符串中. 5)把 world 复制到结果字符串中. 6)更新 str ,使 str 指向结果字符串. 每拼接一次字符串就循环重复2)~6),如果重

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

    而JavaScript的核心是ECMAScript .与其他语言类似,ECMAScript 的字符串是不可变的,即它们的值不能改变. 请考虑下面的代码: 复制代码 代码如下: var str = "hello ";str += "world";实际上,这段代码在幕后执行的步骤如下: 1.创建存储 "hello " 的字符串.2.创建存储 "world" 的字符串.3.创建存储连接结果的字符串.4.把 str 的当前内容复制到结

  • jQuery 剧场版 你必须知道的javascript

    一.摘要 本文是jQuery系列教程的剧场版, 即和jQuery这条主线无关, 主要介绍大家平时会忽略的一些javascript细节.  适合希望巩固javascript理论知识和基础知识的开发人员阅读. 二.前言 最近面试过一些人, 发现即使经验丰富的开发人员, 对于一些基础的理论和细节也常常会模糊. 写本文是因为就我自己而言第一次学习下面的内容时发现自己确实有所收获和感悟.  其实我们容易忽视的javascript的细节还有更多, 本文仅是冰山一角. 希望大家都能通过本文有所斩获. 三.Ja

  • 你必须知道的Javascript知识点之"字面量和对应类型"说明介绍

    代码示例: 复制代码 代码如下: var date1 = new Date(2013,1,1); var date2 = new Date(2013,1,1); date1 == date2;  //执行结果为false date1 === date2;  //执行结果为false var num1 = new Number(10); var num2 = new Number(10); num1 == num2;  //执行结果为false num1 === num2;  //执行结果为fal

  • 你必须知道的Javascript知识点之"单线程事件驱动"的使用

    复制代码 代码如下: var intervalBody = function(){     console.log('interval'); } var startInterval = function(){     setInterval(intervalBody,1000); } var timeoutBody = function(){     console.log('timeout'); } var startTimeout = function(){     setTimeout(t

  • 你必须知道的Javascript知识点之"深入理解作用域链"的介绍

    示例代码: 复制代码 代码如下: var xxxVar1 = 1; var outer = function(){     var xxxVar2 = 2; var results = []; for(var i = 0; i< 3; i++)    {       var inner = function(){          var xxxVar3 = 3;          return xxxVar3 + xxxVar2 +xxxVar1 + i;       }       resu

  • 你必须知道的Javascript知识点之"this指针"的应用

    很多人都知道this指针,这篇文章的主要目的是为了培训我们公司的新人.默认的this指针指向规则1this指针默认指向方法调用时为其指定的对象,如:obj.fun(),fun方法体中的this指针指向obj. 复制代码 代码如下: var user = { name: '段光伟' };user.getName = function(){ return this.name; };user.getName();  //返回'段光伟' 复制代码 代码如下: var user = { name: '段光

  • 你必须知道的JavaScript 变量命名规则详解

    变量命名还应遵守以下某条著名的命名规则: 著名的变量命名规则Camel 标记法首字母是小写的,接下来的字母都以大写字符开头.例如: 复制代码 代码如下: var testValue = 0, secondValue = "hi";Pascal 标记法 首字母是大写的,接下来的字母都以大写字符开头.例如: 复制代码 代码如下: var TestValue = 0, SecondValue = "hi";匈牙利类型标记法 在以 Pascal 标记法命名的变量前附加一个小

  • 3分钟看懂Python后端必须知道的Django的信号机制

    概念 django自带一套信号机制来帮助我们在框架的不同位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(receivers). (感觉就很像Qt的信号与槽机制) 信号系统包含以下三要素: 发送者-信号的发出方 信号-信号本身 接收者-信号的接受者 Django内置了一整套信号,下面是一些比较常用的: Django内置信号 Model signals pre_init # django的modal执行其

  • 必须知道的C语言八大排序算法(收藏)

    概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短: 1.插入排序-直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到

随机推荐