281

I see a few The Code Project solutions.

But is there a regular implementation in JavaScript?

2

11 Answers 11

406

If you have to write code for Internet Explorer make sure you chose an implementation, which uses array joins. Concatenating strings with the + or += operator are extremely slow on IE. This is especially true for IE6. On modern browsers += is usually just as fast as array joins.

When I have to do lots of string concatenations I usually fill an array and don't use a string builder class:

var html = [];
html.push(
  "<html>",
  "<body>",
  "bla bla bla",
  "</body>",
  "</html>"
);
return html.join("");

Note that the push methods accepts multiple arguments.

Sign up to request clarification or add additional context in comments.

4 Comments

And if you're generating output inline, or all members are literals, [foo(), "bar", "baz"].join(""); works, too.
Note that IE here means IE 7 and earlier. In IE 8+ concatenation isn't any worse than other browsers.
This sounds good until allocating extra space isn't an option because it will be directly dependent on number of input creating unnecessary o(n) space complexity. Gotta avoid this.
@TrickOrTreat I think it is necessary, since you either accept the performance pitfalls of concatenation or rely on memory. String builders in C# and Java essentially do the above, although with Char arrays.
79

I just rechecked the performance on http://jsperf.com/javascript-concat-vs-join/2. The test-cases concatenate or join the alphabet 1,000 times.

In current browsers (Firefox, Opera, Internet Explorer 11, and Chrome), "concat" is about 4-10 times faster than "join".

In Internet Explorer 8, both return about equal results.

In Internet Explorer 7, "join" is about 100 times faster unfortunately.

5 Comments

Thanks for this. This should be bumped up in the answer list. It's also a lot faster on IE10 as well (I know that's not a modern browser but I mention it for any potential NMCI developers seeing this).
@Andreas I believe your test is hitting a code path in Chrome where it's never doing the actual concatenate because the string is never read. Even when forcing that, though, the execution speed is still considerably faster: jsperf.com/yet-another-string-concat-test/1
RIP jsperf. I made a jsbench that confirms the same results, at least in my browser (Safari 14): jsben.ch/SrMoI
This result may be misleading because the way the array is expanded to accept new members has an impact on the performance of the join test. Setting the array to a pre-defined starting capacity and doubling the size when the array is full could be significantly more efficient than just calling array.push each time another string is appended.
The symptom for the jsperf.com link is "This Deployment has been disabled. ... 429: TOO_MANY_REQUESTS".
50

No, there is no built-in support for building strings. You have to use concatenation instead.

You can, of course, make an array of different parts of your string and then call join() on that array, but it then depends on how the join is implemented in the JavaScript interpreter you are using.

I made an experiment to compare the speed of str1+str2 method versus array.push(str1, str2).join() method. The code was simple:

var iIterations =800000;
var d1 = (new Date()).valueOf();
str1 = "";
for (var i = 0; i<iIterations; i++)
    str1 = str1 + Math.random().toString();
var d2 = (new Date()).valueOf();
log("Time (strings): " + (d2-d1));

var d3 = (new Date()).valueOf();
arr1 = [];
for (var i = 0; i<iIterations; i++)
    arr1.push(Math.random().toString());
var str2 = arr1.join("");
var d4 = (new Date()).valueOf();
log("Time (arrays): " + (d4-d3));

I tested it in Internet Explorer 8 and Firefox 3.5.5, both on a Windows 7 x64.

In the beginning I tested on small number of iterations (some hundred, some thousand items). The results were unpredictable (sometimes string concatenation took 0 milliseconds, sometimes it took 16 milliseconds, the same for array joining).

When I increased the count to 50,000, the results were different in different browsers - in Internet Explorer the string concatenation was faster (94 milliseconds) and join was slower(125 milliseconds), while in Firefox the array join was faster (113 milliseconds) than string joining (117 milliseconds).

Then I increased the count to 500'000. Now the array.join() was slower than string concatenation in both browsers: string concatenation was 937 ms in Internet Explorer, 1155 ms in Firefox, array join 1265 in Internet Explorer, and 1207 ms in Firefox.

The maximum iteration count I could test in Internet Explorer without having "the script is taking too long to execute" was 850,000. Then Internet Explorer was 1593 for string concatenation and 2046 for array join, and Firefox had 2101 for string concatenation and 2249 for array join.

Results - if the number of iterations is small, you can try to use array.join(), as it might be faster in Firefox. When the number increases, the string1+string2 method is faster.

UPDATE

I performed the test on Internet Explorer 6 (Windows XP). The process stopped to respond immediately and never ended, if I tried the test on more than 100,000 iterations. On 40,000 iterations the results were

Time (strings): 59175 ms
Time (arrays): 220 ms

This means - if you need to support Internet Explorer 6, choose array.join() which is way faster than string concatenation.

5 Comments

join() is part of ECMAScript and afaik every JavaScript interpreter implements it. Why would it "depend"?
he meant HOW it was implemented... if it's implemented in a way that, in a loop, the string is continually appended opposed to created all at once, then using join would be pointless
Yes, it was what I actually meant. Pardon my English ;-) I added results of a comparison how fast which method works in two browsers. You can see, it is different.
IE6, as always, is the exception :)
People with IE6 are used to having everything really slow though. I don't think they'll blame you.
11

That code looks like the route you want to take with a few changes.

You'll want to change the append method to look like this. I've changed it to accept the number 0, and to make it return this so you can chain your appends.

StringBuilder.prototype.append = function (value) {
    if (value || value === 0) {
        this.strings.push(value);
    }
    return this;
}

2 Comments

Why only accept non-NaN numbers and non-empty strings? Your method won't accept null, false, empty strings, undefined, or NaN.
@Elijah - I prefer to keep my StringBuilder class clean by not accepting anything but valid strings and numbers. It is just a personal preference.
7

StringBuilder for JavaScript try this..

  
function StringBuilder(value) {
    this.strings = new Array();
    this.append(value);
}

StringBuilder.prototype.append = function (value) {
    if (value) {
        this.strings.push(value);
    }
}

StringBuilder.prototype.clear = function () {
    this.strings.length = 0;
}

StringBuilder.prototype.toString = function () {
    return this.strings.join("");
}

var sb = new StringBuilder();
sb.append("This is");
sb.append("much better looking");
sb.append("than using +=");

var myString = sb.toString();

sb.clear();

Comments

2

EDIT

No, there is not a built-in class. However, string literals may be a suitable work-around.

ORIGINAL ANSWER

The ECMAScript 6 version (aka ECMAScript 2015) of JavaScript introduced string literals.

var classType = "stringbuilder";
var q = `Does JavaScript have a built-in ${classType} class?`;

Notice that back-ticks, instead of single quotes, enclose the string.

6 Comments

How does this answer the question?
This does not answer the question. At all.
I also don't think it answers the question but some comments are really not helpful or welcoming to other members. At all.
@Theophilus The OP did specify what type of string builder functionality was being sought: That of .NET's System.Text.StringBuilder, a way to concatenate many strings with minimal allocations.
lol downvote because this has nothing to do with stringbuilder..
|
2

Here is a quick example of a StringBuilder class in TypeScript:

export class StringBuilder {
  private _lines: string[] = [];

  write(line: string = ""): void {
    this._lines.push(line);
  }

  writeln(line: string = ""): void {
    this._lines.push(line);
    this._lines.push("\n");
  }

  toString(): string {
    return this._lines.join("");
  }
}

You can use like the following:

const sb = new StringBuilder();
sb.write("Hello World");
sb.writeln("!");
console.log(sb.toString());

Comments

1

For those interested, here's an alternative to invoking Array.join:

var arrayOfStrings = ['foo', 'bar'];
var result = String.concat.apply(null, arrayOfStrings);
console.log(result);

The output, as expected, is the string 'foobar'. In Firefox, this approach outperforms Array.join but is outperformed by + concatenation. Since String.concat requires each segment to be specified as a separate argument, the caller is limited by any argument count limit imposed by the executing JavaScript engine. Take a look at the documentation of Function.prototype.apply() for more information.

1 Comment

This fails in Chrome, since "String.concat" is undefined. Instead, you could use ''.concat.apply('', arrayOfStrings). But this is still a very slow method.
0

When I find myself doing a lot of string concatenation in JavaScript, I start looking for templating. Handlebars.js works quite well keeping the HTML and JavaScript more readable. http://handlebarsjs.com

Comments

-3

In C# you can do something like

 String.Format("hello {0}, your age is {1}.",  "John",  29) 

In JavaScript you could do something like

 var x = "hello {0}, your age is {1}";
 x = x.replace(/\{0\}/g, "John");
 x = x.replace(/\{1\}/g, 29);

6 Comments

I highly doubt running a regular expression in place of a string join will be more performant
Furthermore, this is an awful implementation. It will break if the string with which {0} is replaced contains {1}.
@ikegami the string is not a variable, is a constant, so you know whats contained a priori.
@sports, Copying and pasting all of that throughout your code is an even worse idea.
This does not answer the question. A StringBuilder class is not for string interpolation.
|
-3

Use sys.StringBuilder(). Try the article Sys.StringBuilder Class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.