198

In JavaScript, I have a loop that has many iterations, and in each iteration, I am creating a huge string with many += operators. Is there a more efficient way to create a string? I was thinking about creating a dynamic array where I keep adding strings to it and then do a join. Can anyone explain and give an example of the fastest way to do this?

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
omega
  • 40,311
  • 81
  • 251
  • 474
  • 2
    What are you using the string for? Any performance tips on this are going to vary based on your environment, the sizes of your strings, how a particular js engine optimizes different operations, etc. – Ben McCormick May 22 '13 at 16:10
  • 1
    may be duplicate of http://stackoverflow.com/questions/7299010/why-is-string-concatenation-faster-than-array-join – rab May 22 '13 at 16:11
  • 5
    Check this link http://jsperf.com/join-concat/2 – rab May 22 '13 at 16:12
  • I am using IE9 but its in IE8 compatibility mode (which I can't change). The huge string is something that I will insert into the DOM using jquery. – omega May 22 '13 at 16:13
  • See also [JavaScript string concatenation](http://stackoverflow.com/q/112158/1048572) – Bergi Apr 21 '14 at 15:22

7 Answers7

167

Seems based on benchmarks at JSPerf that using += is the fastest method, though not necessarily in every browser.

For building strings in the DOM, it seems to be better to concatenate the string first and then add to the DOM, rather then iteratively add it to the dom. You should benchmark your own case though.

(Thanks @zAlbee for correction)

Jakub Hampl
  • 39,863
  • 10
  • 77
  • 106
  • 1
    Look into the linked page. Seems like there is little difference between `+=` and doing a join on an array. – Jakub Hampl May 22 '13 at 16:23
  • It seems adding it into the DOM for every string is `66%` (For IE9) faster than creating a string out it and then adding the string to the DOM. – omega May 22 '13 at 16:26
  • the linked page uses += for both tests, no .join() in sight, so it's a meaningless test that only shows noise as any "difference". good example of how noisy js can be though... dom is slower than string, so use it sparingly. – dandavis May 22 '13 at 16:50
  • Time is but one component. For iterative routines, I wonder what the impact to GC is between the various methods? – David Bradley Aug 30 '18 at 20:06
  • For large strings, array.join may be preferable due to string concat's very unpleasant memory bug https://bugs.chromium.org/p/v8/issues/detail?id=3175 – mwag Nov 08 '19 at 00:59
  • 4
    The JSPerf link is dead – Nathan H Aug 18 '20 at 10:41
  • 4
    The web archive version of the JSPerf link: https://web.archive.org/web/20181117202141/jsperf.com/join-concat/2 – Denilson Sá Maia Oct 24 '21 at 17:47
  • Note JSPerf is down, so use https://jsbench.me/ – Janac Meena Mar 11 '22 at 14:30
96

I have no comment on the concatenation itself, but I'd like to point out that @Jakub Hampl's suggestion:

For building strings in the DOM, in some cases it might be better to iteratively add to the DOM, rather then add a huge string at once.

is wrong, because it's based on a flawed test. That test never actually appends into the DOM.

This fixed test shows that creating the string all at once before rendering it is much, MUCH faster. It's not even a contest.

(Sorry this is a separate answer, but I don't have enough rep to comment on answers yet.)

zAlbee
  • 1,160
  • 8
  • 9
  • 5
    I think it worths being an answer on itself because it contains a test and a conclusion (although the test is based/inspired on another answer, that should be ok), no need for the sorry. – user202729 Apr 25 '18 at 16:11
18

Three years past since this question was answered but I will provide my answer anyway :)

Actually, accepted answer is not fully correct. Jakub's test uses hardcoded string which allows JS engine to optimize code execution (Google's V8 is really good in this stuff!). But as soon as you use completely random strings (here is JSPerf) then string concatenation will be on a second place.

  • Interestingly with Chrome 54 and Firefox 45 on my Windows machine, concat is more than twice as fast as the other two using your version. IE 11 has all three as slow as the non-concat in the other two browsers. – ShawnFumo Nov 08 '16 at 18:06
  • 5
    It is different from version to version. I guess, right now Chrome's VM might contain some pre-optimization for this case. I tested again on Chrome v53 and concatenation is now the fastest solution :D Same hardware but different Chrome version gives totally different results. – Volodymyr Usarskyy Nov 19 '16 at 10:39
  • 1
    jsperf is gone. – Boris Verkhovskiy Mar 12 '22 at 09:22
15

I did a quick test in both node and chrome and found in both cases += is faster:

var profile = func => { 
    var start = new Date();
    for (var i = 0; i < 10000000; i++) func('test');
    console.log(new Date() - start);
}
profile(x => "testtesttesttesttest");
profile(x => `${x}${x}${x}${x}${x}`);
profile(x => x + x + x + x + x );
profile(x => { var s = x; s += x; s += x; s += x; s += x; return s; });
profile(x => [x, x, x, x, x].join(""));
profile(x => { var a = [x]; a.push(x); a.push(x); a.push(x); a.push(x); return a.join(""); });

results in node: 7.0.10

  • assignment: 8
  • template literals: 524
  • plus: 382
  • plus equals: 379
  • array join: 1476
  • array push join: 1651

results from chrome 86.0.4240.198:

  • assignment: 6
  • template literals: 531
  • plus: 406
  • plus equals: 403
  • array join: 1552
  • array push join: 1813
Peter Riesz
  • 3,091
  • 29
  • 33
  • 3
    Just played with this. Seems like garbage collection is playing a role here because the first test enjoys a huge advantage regardless of which you choose as first. – JSmart523 Sep 19 '22 at 11:10
  • Although these snippets are invoked many times, they are based on very small strings so overhead (like creating and collecting an array) plays a much larger part in the benchmark than if there were a lot more concatenations per snippet. I think adding a count parameter to go along with the `x` and putting loops into the snippets might give a better picture. – Bill Burdick Mar 14 '23 at 15:41
  • The concern raised by @JSmart523 could be addressed by running a "warmup round" first. – Bill Burdick Mar 14 '23 at 15:43
12

You can also do string concat with template literals. I updated the other posters' JSPerf tests to include it.

for (var res = '', i = 0; i < data.length; i++) {
  res = `${res}${data[i]}`;
}
Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
Madbreaks
  • 19,094
  • 7
  • 58
  • 72
7

I wonder why String.prototype.concat is not getting any love. In my tests (assuming you already have an array of strings), it outperforms all other methods.

perf.link test

Test code:

const numStrings = 100;
const strings = [...new Array(numStrings)].map(() => Math.random().toString(36).substring(6));

const concatReduce = (strs) => strs.reduce((a, b) => a + b);

const concatLoop = (strs) => {
  let result = ''
  for (let i = 0; i < strings.length; i++) {
    result += strings[i];
  }
  return result;
}

// Case 1: 52,570 ops/s
concatLoop(strings);

// Case 2: 96,450 ops/s
concatReduce(strings)

// Case 3: 138,020 ops/s
strings.join('')

// Case 4: 169,520 ops/s
''.concat(...strings)
graup
  • 1,089
  • 1
  • 12
  • 20
  • 2
    Note that the MDN documentation you link to states: It is strongly recommended that the assignment operators (+, +=) are used instead of the concat() method – Josh Dec 02 '20 at 01:14
  • 2
    @Josh yes, but my tests prove that wrong. Either the recommendation is outdated, not applicable to this case, or my test is wrong. – graup Jan 19 '21 at 14:16
  • 2
    In Chromium it works faster, but in Firefox it has terrible performance. Also it has limitation — not more than ~64000 items. – KeyKi Sep 12 '21 at 09:14
  • It is worth noting that `.join()` is also concatenating the (empty) separator between each string. Thus, it may be a bit slower than `.concat()`, but it is also more flexible. If you need a separator, `.join()` is the clear winner. – Denilson Sá Maia Oct 24 '21 at 17:54
  • Note that the performance hint has since been removed from MDN. Concat seems to be the clear winner to me. – graup Jan 23 '23 at 12:31
0

I can't comment on other's answers (not enough rep.), so I will say MadBreaks' answer of using template literals is good, but care should be taken if building a site that needs to be compatible with IE (Internet Explorer), because template literals aren't compatible with IE. So, in that case you can just use assignment operators (+, +=).

Nicolas Mora
  • 41
  • 1
  • 2