Flagrant Badassery

A JavaScript and regular expression centric blog

Faster JavaScript Trim

Since JavaScript doesn't include a trim method natively, it's included by countless JavaScript libraries – usually as a global function or appended to String.prototype. However, I've never seen an implementation which performs as well as it could, probably because most programmers don't deeply understand or care about regex efficiency issues.

After seeing a particularly bad trim implementation, I decided to do a little research towards finding the most efficient approach. Before getting into the analysis, here are the results:

Method Firefox 2 IE 6
trim1 15ms < 0.5ms
trim2 31ms < 0.5ms
trim3 46ms 31ms
trim4 47ms 46ms
trim5 156ms 1656ms
trim6 172ms 2406ms
trim7 172ms 1640ms
trim8 281ms < 0.5ms
trim9 125ms 78ms
trim10 < 0.5ms < 0.5ms
trim11 < 0.5ms < 0.5ms

Note 1: The comparison is based on trimming the Magna Carta (over 27,600 characters) with a bit of leading and trailing whitespace 20 times on my personal system. However, the data you're trimming can have a major impact on performance, which is detailed below.

Note 2: trim4 and trim6 are the most commonly found in JavaScript libraries today.

Note 3: The aforementioned bad implementation is not included in the comparison, but is shown later.

The analysis

Although there are 11 rows in the table above, they are only the most notable (for various reasons) of about 20 versions I wrote and benchmarked against various types of strings. The following analysis is based on testing in Firefox 2.0.0.4, although I have noted where there are major differences in IE6.

  1. return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    All things considered, this is probably the best all-around approach. Its speed advantage is most notable with long strings — when efficiency matters. The speed is largely due to a number of optimizations internal to JavaScript regex interpreters which the two discrete regexes here trigger. Specifically, the pre-check of required character and start of string anchor optimizations, possibly among others.
  2. return str.replace(/^\s+/, '').replace(/\s+$/, '');
    Very similar to trim1 (above), but a little slower since it doesn't trigger all of the same optimizations.
  3. return str.substring(Math.max(str.search(/\S/), 0), str.search(/\S\s*$/) + 1);
    This is often faster than the following methods, but slower than the above two. Its speed comes from its use of simple, character-index lookups.
  4. return str.replace(/^\s+|\s+$/g, '');
    This commonly thought up approach is easily the most frequently used in JavaScript libraries today. It is generally the fastest implementation of the bunch only when working with short strings which don't include leading or trailing whitespace. This minor advantage is due in part to the initial-character discrimination optimization it triggers. While this is a relatively decent performer, it's slower than the three methods above when working with longer strings, because the top-level alternation prevents a number of optimizations which could otherwise kick in.
  5. str = str.match(/\S+(?:\s+\S+)*/);
    return str ? str[0] : '';

    This is generally the fastest method when working with empty or whitespace-only strings, due to the pre-check of required character optimization it triggers. Note: In IE6, this can be quite slow when working with longer strings.
  6. return str.replace(/^\s*(\S*(\s+\S+)*)\s*$/, '$1');
    This is a relatively common approach, popularized in part by some leading JavaScripters. It's similar in approach (but inferior) to trim8. There's no good reason to use this in JavaScript, especially since it can be very slow in IE6.
  7. return str.replace(/^\s*(\S*(?:\s+\S+)*)\s*$/, '$1');
    The same as trim6, but a bit faster due to the use of a non-capturing group (which doesn't work in IE 5.0 and lower). Again, this can be slow in IE6.
  8. return str.replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');
    This uses a simple, single-pass, greedy approach. In IE6, this is crazy fast! The performance difference indicates that IE has superior optimization for quantification of "any character" tokens.
  9. return str.replace(/^\s*([\S\s]*?)\s*$/, '$1');
    This is generally the fastest with very short strings which contain both non-space characters and edge whitespace. This minor advantage is due to the simple, single-pass, lazy approach it uses. Like trim8, this is significantly faster in IE6 than Firefox 2.

Since I've seen the following additional implementation in one library, I'll include it here as a warning:

return str.replace(/^\s*([\S\s]*)\b\s*$/, '$1');

Although the above is sometimes the fastest method when working with short strings which contain both non-space characters and edge whitespace, it performs very poorly with long strings which contain numerous word boundaries, and it's terrible (!) with long strings comprised of nothing but whitespace, since that triggers an exponentially increasing amount of backtracking. Do not use.

A different endgame

There are two methods in the table at the top of this post which haven't been covered yet. For those, I've used a non-regex and hybrid approach.

After comparing and analyzing all of the above, I wondered how an implementation which used no regular expressions would perform. Here's what I tried:

function trim10 (str) {
	var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
	for (var i = 0; i < str.length; i++) {
		if (whitespace.indexOf(str.charAt(i)) === -1) {
			str = str.substring(i);
			break;
		}
	}
	for (i = str.length - 1; i >= 0; i--) {
		if (whitespace.indexOf(str.charAt(i)) === -1) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}

How does that perform? Well, with long strings which do not contain excessive leading or trailing whitespace, it blows away the competition (except against trim1/2/8 in IE, which are already insanely fast there).

Does that mean regular expressions are slow in Firefox? No, not at all. The issue here is that although regexes are very well suited for trimming leading whitespace, apart from the .NET library (which offers a somewhat-mysterious "backwards matching" mode), they don't really provide a method to jump to the end of a string without even considering previous characters. However, the non-regex-reliant trim10 function does just that, with the second loop working backwards from the end of the string until it finds a non-whitespace character.

Knowing that, what if we created a hybrid implementation which combined a regex's universal efficiency at trimming leading whitespace with the alternative method's speed at removing trailing characters?

function trim11 (str) {
	str = str.replace(/^\s+/, '');
	for (var i = str.length - 1; i >= 0; i--) {
		if (/\S/.test(str.charAt(i))) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return str;
}

Although the above is a bit slower than trim10 with some strings, it uses significantly less code and is still lightning fast. Plus, with strings which contain a lot of leading whitespace (which includes strings comprised of nothing but whitespace), it's much faster than trim10.

In conclusion…

Since the differences between the implementations cross-browser and when used with different data are both complex and nuanced (none of them are faster than all the others with any data you can throw at it), here are my general recommendations for a trim method:

  • Use trim1 if you want a general-purpose implementation which is fast cross-browser.
  • Use trim11 if you want to handle long strings exceptionally fast in all browsers.

To test all of the above implementations for yourself, try my very rudimentary benchmarking page. Background processing can cause the results to be severely skewed, so run the test a number of times (regardless of how many iterations you specify) and only consider the fastest results (since averaging the cost of background interference is not very enlightening).

As a final note, although some people like to cache regular expressions (e.g. using global variables) so they can be used repeatedly without recompilation, IMO this does not make much sense for a trim method. All of the above regexes are so simple that they typically take no more than a nanosecond to compile. Additionally, some browsers automatically cache the most recently used regexes, so a typical loop which uses trim and doesn't contain a bunch of other regexes might not encounter recompilation anyway.


Edit (2008-02-04): Shortly after posting this I realized trim10/11 could be better written. Several people have also posted improved versions in the comments. Here's what I use now, which takes the trim11-style hybrid approach:

function trim12 (str) {
	var	str = str.replace(/^\s\s*/, ''),
		ws = /\s/,
		i = str.length;
	while (ws.test(str.charAt(--i)));
	return str.slice(0, i + 1);
}

New library: Are you a JavaScript regex master, or want to be? Then you need my fancy XRegExp library. It adds new regex syntax (including named capture and Unicode properties); s, x, and n flags; powerful regex utils; and it fixes pesky browser inconsistencies. Check it out!

There Are 187 Responses So Far. »

  1. Great work Steve. Grats on blowing the pants off the competition. Parsing the Magna Carta 20 times in less than a millisecond is flagrantly badass indeed.

  2. [...] 11 funciones trim() puestas a prueba dan como resultado una interesante estadística que nos permite seleccionar la que más nos interese. [...]

  3. Thanks, Shady. But really, the competition is regular expression engines themselves and how to best take advantage of them. I doubt many JavaScripters who’ve written a trim function have spent much time considering alternative approaches.

  4. After looking at your comparison of trim methods (which in my oppinion is quite interesting) I found minor bugs in your trim10 and trim11 methods. It seems that your array indices and arguments to substr are off by 1. Consider this, for a hopefully correct trim11:
    function trim( str ) {
    str = str.replace(/^\s+/, ”);
    for( var i = str.length-1; i > 0; –i ) {
    if( /\S/.test( str[i] ) ) {
    str = str.substring( 0, i+1 );
    break;
    }
    }
    return str;
    }

  5. Fixed. Thanks.

    By the way, I’d recommend avoiding treating strings as arrays to look up character indexes like that (e.g., str[i]). It’s not part of the ECMA-262 3rd Edition standard and doesn’t work correctly in IE. Better to stick with the charAt method for accurate lookups.

  6. [...] “Trim” the Holdup What if we created a hybrid implementation which combined a regex’s universal efficiency at trimming leading whitespace with the alternative method’s speed at removing trailing characters? (tags: RegEx JavaScript) [...]

  7. Cool! Great work. This kind of research should be done more often.

    I found this article, because Dean Edwards used the research for the base2 project (http://code.google.com/p/base2/). I actually did some tests on the Mac and made even another implementation, see my website.

  8. Thanks, Doeke! And thanks for mentioning that Dean Edwards referenced this in Base2, as I hadn’t known that previously. (By the way, through referrer logs I’ve so far discovered this post also referenced in implementations by or discussions with the developers of jQuery, Ext, Rails, and CFJS.)

    For other readers, see Doeke Zanstra’s blog post for performance times of the above trim functions in several WebCore, Gecko, and Presto based browsers on Mac OS, and a better version of trim10.

  9. [...] Levithan has put together by far the most extensive analysis of JavaScript and trim I have seen (thanks for the tip Dean). We’ll certainly use this knowledge in Dojo 0.9 and [...]

  10. Just wanted to let you know Steve, that since being pointed at your blog by Dean Edwards, that its been added to the list of RSS feeds for our News Aggregator (Planet Dojo) at http://dojotoolkit.org

    Great article and very interesting articles all around on your blog. Keep up the great work!

    -Karl

  11. Karl, that’s awesome! Thanks for the heads up.

  12. Interesting. My firefox actually ran trim10 the fastest. Constantly return near 0ms times. A bug perhaps, or was it just that speedy?

    If I cranked it up to 60 iterations, it would show 10ms.

    Regardless, very nice work.

  13. Jeff, it’s just that speedy. :) With the given test of trimming the Magna Carta with small amounts of whitespace at both ends, trim10 certainly should be the fastest of those shown here.

    But as this blog post explains in some detail, none of these are the one-true fastest. Their comparative speeds depend largely on the data they’re fed, although some are more consistent than others cross-browser and/or with any given data.

    Trim10′s strength is that, apart from edge whitespace, the length of the string has very little impact on its performance. Its weakness is strings which contain large amounts of leading or trailing whitespace, since a loop over each character won’t traverse that nearly as fast as a simple regex. That’s why I recommended trim11 over trim10, as although it’s a little slower than trim10 with many types of strings, it removes one of trim10′s weaknesses vs. the regex-based functions (long, leading whitespace).

  14. True, but in all honesty, I’ve never really run into cases in the wild where the trimming that needed to be done was that out of hand.

    Sure, if I make up data to be cleaned and stuff the snot outta it with spaces, it pokes a hole in the looping method — but I’ve never encountered that IRL.

    So for me, I’ll happily gank trim10 :D Thanks!

  15. Shortest notation:

    function trim(str)
    {
    str = str.replace(/^\s+/, ”)
    for (var i = str.length; i–;)
    if (/\S/.test(str.charAt(i)))
    return str.substring(0, ++i)
    return str
    }

  16. Hi Steven, great article!
    I gave it a try and wrote my own trim.. if you are interested, here’s an implementation, I tried to make it work as fast as yours.
    In my PC it is sometimes a bit faster, sometimes equal.
    I created a 27k long string, with 300 spaces on each side, using less than that, both were always giving 0ms….
    Here’s the example: http://www.freewebs.com/flesler/Trim/

    And here’s the piece of code:

    var trim = (function(){
        var ws = {},
            chars = ' \n\r\t\v\f\u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
        for(var i = 0; i < chars.length; i++ )
            ws[chars.charAt(i)] = true;


        return function( str ){
            var s = -1,
                e = str.length;
            while( ws[str.charAt(--e)] );
            while( s++ !== e && ws[str.charAt(s)] );
            return str.substring( s, e+1 );
        };
    })();

  17. @Ariel: Nicely done. :-)

  18. Thanks! and thank you for clearing up my mess :D

  19. Hi,

    Good thinking and nice research!

    I was curious about already existing trim implementations and your article sums them up very nicely. Still, playing myself a little bit and being the regex lover that I am, I came up with the simpliest implementation that I could think off and I was wondering what you think about it.

    String.prototype.trim = function() {

    return this.replace(/^\s*(\S.*\S)?\s*$/, ‘$1′);

    }

    I haven’t test for speed or browser compatibility issues (I have just to support Firefox 2 & IE7 at the time being) and I’m not *very* concerned about a couple of ms difference so it could very well not be an alternative at all. Still, I’d love to hear what you have to say about it :D

  20. Thanks, Nacho! Re: your implementation, it is not equivalent to the others shown (in other words it’s broken). Two reasons:

    - It will not work with strings which have just one non-whitespace character.
    - Since JavaScript doesn’t have a “single-line” mode you need to replace the dot with [\S\s] (or similar).

    In any case, /^\s+|\s+$/g is already more “simple” if you measure by readability (arguably) or number of characters.

  21. You completely got me there. I’m glad I posted it :)

    It’s of course true, it wouldn’t validate a one non-whitespace character string. Silly that it could scape my attention.

    About the “single line” mode I’m not so sure I follow you. I thought JavaScript had a flag (m) for multiline matching and therefore assumed that when the flag is not present matching only takes place on a single line strings … then again I do not know the internals as far as you do …

    I guess I’ll have to give 1 or 11 a go ;)

    Thanks for the comment!

  22. The regex terms single-line and multi-line are confusing for many people, which is why I shun them in RegexPal in favor of the more descriptive “^$ match at line breaks” (instead of “multi-line”) and “dot matches newline” (instead of “single-line”). However, “dot matches newline” mode is not available natively in JavaScript… it’s provided by XRegExp.

    In other words, without XRegExp, JavaScript provides no way for the regex dot to match all characters including newlines. Multi-line mode changes the meaning of the “^” and “$” tokens — it has nothing to do with what the dot matches.

  23. [...] know my audience doesn’t care much for Web Development content, but this was a fascinating article about the various methods of trimming the white space from a text [...]

  24. [...] Doug D started a thread on the google groups jQuery developer list about a faster trim method he ran across and how counter intuitively it was better to run two expressions rather than one. Matt Kruse then provided a link to a great article on the subject: http://blog.stevenlevithan.com/archives/faster-trim-javascript [...]

  25. Hey Steve, excellent analysis. Thought I’d throw in my two cents here; after slogging through it, I saw Ariel already posted a near-verbatim version of the trim10 redux I’d written. :)
    I did a bit of extensive testing based on your test example using variations of #10 and #11. Like you said, while #10 is nice and zippy when there’s no leading space, it’s just too slow when there’s any significant leading space. So I went with #11, and here’s what I ended up with. (Brevity first, as always! :) )

    function trim13 (str)
    {
    var str = str.replace(/^\s*/, “”), s = /\s/, i = str.length;
    while (s.test(str.charAt(–i)));
    return str.substring(0, i + 1);
    }

    Just putting the /\S/ regex (from #11) outside of the loop sped it up for starters, about twice as fast on runs of 10000 times. A notable quirk I found with the /^\s+/ regex: it performs much worse (3400ms vs. 470ms) on strings with no leading whitespace, compared to strings with even a single leading space. Perhaps you could explain that better, but it seems /^\s*/ keeps a consistent performance in both cases.

    On a different note, we seem to share the same taste in alcohol. :) Vodka + Red Bull is my mainstay at any bar, but my vodka of choice happens to be Grey Goose. And I drink entirely too much Red Bull – 4 to 6 cans on a usual workday. Keeps you running, no? ~_^

  26. Oh, and one more thing about the trim10 function as you have it posted now. IE doesn’t recognize ‘\v’ as a metacharacter in Javascript strings, so a literal ‘v’ ends up in the whitespace string. Try trimming a string starting with ‘v’ – it’ll chop the leading ‘v’ as well. (That one drove me nuts for a full 20 minutes.) Replace it with \x0b and all’s well. ^_^

  27. @Scott Trenda, interesting about IE not interpreting \v as a vertical tab when embedded in a string literal, especially since it is handled correctly in regexes (/\v/.test("\x0b") == true). I’ll fix that in trim10.

    I’ve actually been using something very similar to your trim13 recently. The only (edge case) problem is that browsers interpret \s differently (see JavaScript, Regex, and Unicode, and the test page). I’ve left the very quick and dirty trim10/11 up there since their ugliness seems to have inspired others to improve them.

    As for your observations about ^\s* vs. ^\s+, that depends on the implementation. Another alternative to consider is ^\s\s*. The difference stems from internal optimizations like whether or not a pre-check of required characters is performed, and the relative cost of success vs. failure to match.

  28. [...] Simon found this gem. Steven Levithan wrote about optimizing a JavaScript trim. [...]

  29. The method that GWT uses to translate String.trim():

    public native String trim() /*-{
    var r1 = this.replace(/^(\s*)/, ”);
    var r2 = r1.replace(/\s*$/, ”);
    return r2;
    }-*/;

  30. Is really actual on “MS Windows” and “Internet Explorer”? you cannot fix bugs by javascript.

  31. Hi,

    nice work. But one thing I’m missing is point to different /s handling in browsers.

    ECMAScript specifies \s as [\t\n\v\f\r], Firefox added [\u00A0\u2028\u2029] to the list.

    Opera happens to match   with \s like Firefox. Safari behaves like the IE and doesnt match &nbsp with \s.

    more: http://dev.mootools.net/ticket/646

    I didnt test \u2028 and \u2029, but I think /[\s\u00A0\u2028\u2029]+/g should fix this for all browsers, as it adds firefox`s additions to \s.

  32. @Daniel Steigerwald, that’s not entirely correct. See my post on JavaScript, regex, and Unicode for more information about what \s should and does match.

  33. [...] Simon found this gem. Steven Levithan wrote about optimizing a JavaScript trim. [...]

  34. ERROR in function 10 and 11:

    for (var i = str.length – 1; i > 0; i–) {
    => for (var i = str.length – 1; i >= 0; i–) {

  35. @Tiziano, that is not an error. The way they are written, there is no reason for the backwards loops to be concerned about the character at index 0.

  36. It seems to me that your loop does far more work than necessary. Why shorten the string one character at a time? Keep the loop counter around and you can do all the shortening at once. That’s bound to be faster.

    var i = str.length - 1;
    while ( i >= 0 && /\s/.test(str.charAt(i)) ) --i;
    str = str.substring(0, i + 1);

    Also, it might be worth pulling the regex construction out of the loop; that depends on how well Javascript compilers optimise.

    var ws = /\s/;
    while ( i >= 0 && ws.test(str.charAt(i)) ) --i;

  37. there is no reason for the backwards loops to be concerned about the character at index 0.

    True, but anyone who ever modifies the code needs to be aware that there’s an inactive bug in the code, lest they accidentally activate it. And it doesn’t cost anything at all to make the check correct. So there’s no reason not to fix it.

  38. @Aristotle Pagaltzis, putting the regex outside the loop shouldn’t matter according to ECMA-262 3rd Edition since the spec states that regex literals cause only one object to be created at runtime for a script or function. However, most implementations don’t respect that (Firefox does), and in any case the behavior is proposed to be changed in ECMAScript 4.

    Regarding changing the loop counter to allow an extra iteration… I’ve realized that Tiziano was correct. It was in fact an error in the case where there is whitespace to the right and only one non-whitespace character. I’ve fixed it, but the trim10/11 implementations are ugly anyway, as you’ve pointed out. Although I’ve intentionally been avoiding this for some time, I’ve gone ahead and edited the post to show a cleaner version of the trim11 approach at the end (which is nearly identical to what Scott Trenda posted earlier).

  39. [...] is an older article, but Steven Levithan has an article posted on his site regarding how to do a faster trim function in JavaScript. His demo page has eleven different trim implementations and some example text to test them out [...]

  40. Did anybody tried str.lastIndexOf() to find the trailing blanks ?

  41. [...] JavaScript Trim Optimizations February 4, 2008 – 2:32 pm | by SiNi Simon found this gem. Steven Levithan wrote about optimizing a JavaScript trim. [...]

  42. @Yves:

    You can’t use lastIndexOf for this problem. That method only gives you a way to ask for the last appearance of a specific character, but what we need is a way to ask for the last appearance of any other character than a space. Additionally, \s in a regex doesn’t find just space characters, but a number of other whitespace characters as well. You can’t do that with lastIndexOf at all.

    @Steve:

    Now that I think of it, how does the following version fare?

    return str.replace(/^\s+/, '').replace(/.*\s+$/, '');

    This should be faster than any of the regex approaches you showed above. A class like [\s\S] is kinda silly – “match anything that’s whitespace or is not whitespace” is just a long-winded way to say “match anything,” except that non-IE browsers should be able to optimise it as well, and in fact many regex engines have special optimisations for .* built in. This should gobble up the entire string immediately and then do the same backtrack-loop as the explicit Javascript code does, except without crossing back and forth between the JS VM and the RE engine at every backtracking step in order to involve the JS VM dispatcher.

    But that’s just theory-based hypothesis – benchmarking is in order to confirm (or disprove) it.

  43. Oh! D’uh. Disregard the above suggestion. That won’t work for obvious reasons.

    I got confused because I do this in conjunction with \zs in Vim all the time. In Vim you could write s/.*\zs\s\s*$// and it would replace just the part after the \zs. In Perl 5.10 you can do the same using the \K escape. But Javascript has neither extension, so… yeah.

  44. \K would be very nice to have, especially since JavaScript has no lookbehind. But yeah, you can’t do that. Note that something like [\S\s] is necessary because JavaScript has no “single-line” (dot matches all) mode.

  45. OK, I think I’ve unbrainfarted myself enough to actually try my idea of using a greedy match and RE engine backtracking. Sorry for all the noise. Here’s trim12:

    function trim12 (str) {
        var str = str.replace(/^\s\s*/, ''),
        len = str.length;
     
        if (len && /\s/.test(str.charAt(len-1)) {
            var re = /.*\S/g;
            re.test(str);
            str = str.slice(0, re.lastIndex);
        }
     
        return str;
    }

    The trick here is as follows. The inner regex is run only if the string is non-empty, which means there must be non-whitespace characters in it, because otherwise the first substitution would have left an empty string, and only if the last character is whitespace. In that case, we run a global match that first gobbles up the entire string using .*, then backtracks until it can match \S. We know it must match because at this point we know the string ends with whitespace and we know it has non-whitespace characters in it. After the match, because it is global (/g flag), the position of the character after the end of the match will be recorded in the lastIndex property of the regex object.

    So we just use that to return the portion of the string before it.

    Please benchmark this. I’ve tested it and I know it works; now the question is how fast it is.

  46. JavaScript has no “single-line” (dot matches all) mode.

    Argh, now I see that. I guess explicitness would demand [-\uFFFF], but that’s clearly more cumbersome to type and read than [\s\S]. Sigh.

    (Hopefully I will stop spamming your comments now. Sorry again.)

  47. Is there any performance gain from using /\s*\s$/ instead of /\s+$/ or /\s*$/?

  48. [...] Faster JavaScript Trim Since JavaScript doesn’t include a trim method natively, it’s included by countless JavaScript libraries – usually as a global function or appended to String.prototype. (tags: javascript performance trim regex string optimization regexp tips **) [...]

  49. [...] Faster JavaScript Trim (tags: javascript regex) [...]

  50. [...] per la visita!Steven Levithan ha sentito la necessità (ebbravo!) di studiare come sia possibile ottimizzare la funzione trim che di solito viene inclusa come libreria esterna in Javascript. La conclusione è la seguente (vi [...]

  51. Funny, IE beats Firefox most of the rounds. If only they have spent as much effort on adhering to the standard…

  52. [...] http://blog.stevenlevithan.com/archives/faster-trim-javascript (tags: benchmark development javascript optimization trim regex string) [...]

  53. Steve, I have a couple of questions about the 2008-02-04 update:

    1) What happens in the empty string case? Seems like “i” is -1 and bad stuff should happen?

    2) What’s the licensing around this? I’d like to use it in GWT (we’re Apache 2.0).

    Thanks,
    Scott

  54. @Scott Blum:

    1. An i value of -1 works fine because charAt returns an empty string if the provided index is out of range.

    2. Any code I post on my blog is under the MIT license unless otherwise specified. But something this simple I’d consider public domain. You’re certainly very welcome to use it in GWT.

  55. Hello, nice article. Using the benchmark page with Opera 9.5 beta snapshot build 9755 on Windows, I got some interesting results.

    With 20 iterations the methods 1-8 were between 150 and 450 ms, trim9 took almost 4 seconds! trim10 and trim12 were 0 ms every time, but trim11 was at 15 ms.

    With 100 iteration the methods 1-8 were quite similar as with 20 iterations, but the values five times larger naturally. Similarly trim9 was almost 19 seconds (slow!). Still trim10 gave a nice result of 0 ms, while both trim11 and trim12 were 47 ms.

    With 200 iterations I finally managed to make trim10 take more than 0 ms of time, it took 15 ms in one run, which itself took almost a minute to run, thanks to trim9′s slow 39 seconds of execution time! Here, however, trim12 was slower than trim11 for some reason, while with 20 iterations it was always a lot faster.

    So, at least with Opera 9.5 it seems like the method 10 is clearly superior to all of the other methods.

  56. @Joonas Lehtolahti, that may be true with the provided test data, but this post makes it clear that none of the methods are fastest with all types of strings.

    Trim9 is slow in Opera because that browser is particularly bad at lazy quantification.

  57. [...] Javascript ile metin kırma işlemleri ve hız faktörü hakkında bir makale. Bağlantı [...]

  58. It seems to me that the right trim of #1 is a little out of order. The current #1 trim shows:

    str.replace(/^\s\s*/, ”).replace(/\s\s*$/, ”);

    Shouldn’t it be changed to:

    str.replace(/^\s\s*/, ”).replace(/\s*\s$/, ”);

    It is symmetric with the left trim and it would seem that a pre-check optimization could potentially be more easily performed by using only the last character. [I admit that I might be over-thinking this...]

  59. @Chris Akers, you are assuming that such a pre-check would account for position relative to particular anchors within the string. That is unlikely. But more importantly, you would potentially be making the second regex take longer to fail at positions prior to string-ending whitespace. That tiny bit of extra time (assuming the absence of certain types of other potential internal optimizations) would add up over the course of checking every position in a long string.

  60. [...] Faster JavaScript Trim. Neat optimisation post—it turns out that while regular expressions are great for removing leading whitespace you can do a lot better at trailing whitespace by manually looping backwards from the end of the string. [...]

  61. What about something like this?

    String.prototype.trim = function(){
    var s = /\s*([\S+\s*]*\S+)+\s*/i.exec(this);
    return (!s) ? ” : s[1];
    }

  62. [...] note: I found this nifty site that compares a variety of String.trim methods ( I wonder how mine compares ), it’s worth reading : Faster JavaScript Trim [...]

  63. @Sean, I think you fundamentally misunderstand how your regular expression works. For starters, you should read up on regex character class syntax. With all whitespace, your regular expression manages to be orders of magnitude worse performing than every other regular expression on this page, including the one that was so bad I had to leave it out of the speed tests.

  64. function trim13 (str) {
    var ws = /\s/, _start = 0, end = str.length;
    while(ws.test(str.charAt(_start++)));
    while(ws.test(str.charAt(–end)));
    return str.slice(_start – 1, end + 1);
    }

    You can find the benchmark results on my related post:
    http://lucaguidi.com/2008/5/28/faster-javascript-trim

  65. @Luca Guidi, very nice list of browser results. However, the copy of my benchmark page you’re providing changes the test in a subtle but important way — it removes all the leading whitespace, and all but the very last trailing whitespace character. That means the test methods in your while loops run fewer times.

    The more leading whitespace you have, the slower that testing each character will be when compared to removing it all in one shot with replace. It’s not accurate to claim (without qualifiers) that your implementation is “the fastest one,” because that doesn’t hold true with certain types of subject data. According to my brief test in Firefox 2.0.0.14, with enough leading whitespace your implementation becomes much slower than all the others.

  66. @Steve, I’m very sorry for this, I just downloaded your page and added my version of the trim function.
    I didn’t noticed the missing whitespaces, maybe the browser stripped them.
    I’ll run again all the test suite, then update the results.
    Thanks for the hint!

  67. I updated test results on my post.

  68. I liked trim10!
    I was going to mention about the i >=0 en the second loop.
    There is no bug in i > 0, it is how the algorithm was thought. You are now checking twice for character (0).
    Thanks for this beautiful page!

  69. I’ve found that your hybrid solution, along with a few of the others, is flawed in IE6. A single space ' ' will not be trimmed in IE6 but will in FF3. I’m a little stumped right now so I don’t have any fixes for you. I can’t see why the first replace, str.replace(/^\s\s*/, '') isn’t picking it up in IE6

  70. I lied. It isnt a single space thats the problem it’s because I have the html entity, &nbsp;

  71. [...] alors simplifions cette tâche une bonne fois pour toute. La méthode utilisée a été prise dans Flagrant Badassery. String.prototype.trim = function ( str ) { return str.replace(/^ss*/, [...]

  72. Hi, I have build a page to test the methods above, just for fun, I hope you’ll like it. Thanks.
    http://guitarbean.com/topic/javascript-trim/

  73. Hi, folks!

    This is a very good work, thanks for sharing! I’ve just tweaked it a little, so that you can call the trim function as if it were a member of String. You just have to add this:

    String.prototype.trim = function()
    {
    var str = this;
    str = str.replace(/^\s\s*/, ”),
    ws = /\s/,
    i = str.length;
    while (ws.test(str.charAt(–i)));
    return str.slice(0, i + 1);
    }

    This way, you can do like:

    var myString = ” bla bla bla “;
    alert(myString.trim());

  74. your like a hacker personality steve..

    phillipe -> your benchmark is great..

  75. Can you try this method :

    function trim(str) {
    return str.replace(/^\s*(\b.*\b|)\s*$/, “$1″);
    }

    I found this method in Rialto framework.

    Thanks,

  76. I tested my version of trim() and found that it is as much as 3 times faster than the code here.

    String.whiteSpace =
    {
    “\u0009″ : true, “\u000a” : true, “\u000b” : true, “\u000c” : true, “\u000d” : true, “\u0020″ : true, “\u0085″ : true,
    “\u00a0″ : true, “\u1680″ : true, “\u180e” : true, “\u2000″ : true, “\u2001″ : true, “\u2002″ : true, “\u2003″ : true,
    “\u2004″ : true, “\u2005″ : true, “\u2006″ : true, “\u2007″ : true, “\u2008″ : true, “\u2009″ : true, “\u200a” : true,
    “\u200b” : true, “\u2028″ : true, “\u2029″ : true, “\u202f” : true, “\u205f” : true, “\u3000″ : true
    };

    /*
    * Trim spaces from a string on the left and right.
    */

    trim13 = function(str)
    {
    str = String(str);

    var n = str.length;
    var s;
    var i;

    if (!n)
    return str;
    s = String.whiteSpace;
    i = 0;
    if (n && s[str.charAt(n-1)])
    {
    do
    {
    –n;
    }
    while (n && s[str.charAt(n-1)]);
    if (n && s[str.charAt(0)])
    do
    {
    ++i;
    }
    while (i < n && s[str.charAt(i)]);
    return str.substring(i, n);
    }
    if (n && s[str.charAt(0)])
    {
    do
    {
    ++i;
    }
    while (i < n && s[str.charAt(i)]);
    return str.substring(i, n);
    }
    return str;
    };

  77. I have significantly improved the previous version. I also added tests for strings with no leading / trailing spaces because it is extremely common to trim strings that do not need triming. The improved version is faster than trim1 – trim12 on all tested browsers (chrome, ie 6,7,8, ff 2,3,3b, opera 9.62, safari 3.1.2) for all test cases except that FF 3x browsers sometimes are slightly faster with a regexp when spaces have to be trimmed. However, it is not always the SAME regexp. In many cases, the speedup is as much as a factor of 20 over the regexp methods.

    String.whiteSpace = [];
    String.whiteSpace[0x0009] = true;
    String.whiteSpace[0x000a] = true;
    String.whiteSpace[0x000b] = true;
    String.whiteSpace[0x000c] = true;
    String.whiteSpace[0x000d] = true;
    String.whiteSpace[0x0020] = true;
    String.whiteSpace[0x0085] = true;
    String.whiteSpace[0x00a0] = true;
    String.whiteSpace[0x1680] = true;
    String.whiteSpace[0x180e] = true;
    String.whiteSpace[0x2000] = true;
    String.whiteSpace[0x2001] = true;
    String.whiteSpace[0x2002] = true;
    String.whiteSpace[0x2003] = true;
    String.whiteSpace[0x2004] = true;
    String.whiteSpace[0x2005] = true;
    String.whiteSpace[0x2006] = true;
    String.whiteSpace[0x2007] = true;
    String.whiteSpace[0x2008] = true;
    String.whiteSpace[0x2009] = true;
    String.whiteSpace[0x200a] = true;
    String.whiteSpace[0x200b] = true;
    String.whiteSpace[0x2028] = true;
    String.whiteSpace[0x2029] = true;
    String.whiteSpace[0x202f] = true;
    String.whiteSpace[0x205f] = true;
    String.whiteSpace[0x3000] = true;

    /*
    * Trim spaces from a string on the left and right.
    */

    trim13 = function(str)
    {
    var n = str.length;
    var s;
    var i;

    if (!n)
    return str;
    s = String.whiteSpace;
    if (n && s[str.charCodeAt(n-1)])
    {
    do
    {
    –n;
    }
    while (n && s[str.charCodeAt(n-1)]);
    if (n && s[str.charCodeAt(0)])
    {
    i = 1;
    while (i < n && s[str.charCodeAt(i)])
    ++i;
    }
    return str.substring(i, n);
    }
    if (n && s[str.charCodeAt(0)])
    {
    i = 1;
    while (i < n && s[str.charAt(i)])
    ++i;
    return str.substring(i, n);
    }
    return str;
    };

  78. I posted a follow up on this good ol’ thread:
    http://flesler.blogspot.com/2008/11/fast-trim-function-for-javascript.html

  79. [...] Javascript string trim function implementations and comparison http://blog.stevenlevithan.com/archives/faster-trim-javascript [...]

  80. Hi,

    Do you try the trim function of FireFox 3.1 ?
    it’s non standard function …

    https://developer.mozilla.org/en/Firefox_3.1_for_developers

    in the Javascript section.

  81. [...] queira se aprofundar no assunto, aconselho a leitura do artigo Faster JavaScript Trim que mostra vários testes de performance no IE e [...]

  82. [...] אני מפנה אותכם למאמר מעניין בנוגע לשיטות שונות כיצד לבצע את ×” regular expression והמשמעויות על ביצעים – ומתי להשתמש במה – כאן [...]

  83. Impressive! Good work Steve

  84. [...] functions There is an interseting examination of varions trim functions here: <URL: http://blog.stevenlevithan.com/archi…rim-javascript > The best all-round function seems to be trim3 when strings have lots of leading and trailing [...]

  85. Because of the regexp internals, the fastest trim is /^[^\S]+/ and /^[^\S]+$/, trust me.

  86. The second should be of course /[^\S]+$/. They both work in O(n), no wasteful backtracking.

  87. [...] blog.stevenlevithan.com/archives/faster-trim-javascript Since JavaScript doesn’t include a trim method natively, it’s included by countless [...]

  88. Your site doesn’t correctly work in safari browser

  89. Thanks man! greate work!

  90. function trimstr(str)
    {
    var whitespace= " \n\r\t\f";

    for( var i= 0; i < str.length; i++ )
    if( whitespace.indexOf( str.charAt(i) ) < 0 )
    break;

    for( var j= str.length – 1; j >= i; j– )
    if( whitespace.indexOf( str.charAt(j) ) < 0 )
    break;

    return str.substring( i,j+1 );
    }

  91. [...] Levithan has discussed the trim method in great [...]

  92. [...] queira se aprofundar no assunto, aconselho a leitura do artigo Faster JavaScript Trim que mostra vários testes de performance no IE e [...]

  93. [...] are well-crafted, but I think plain old loops can do better. Back in 2007, Steve Levithan covered some really fast implementations of trim() followed by a few more articles by others, including Luca [...]

  94. Here’s an even faster implementation of trim() based on Michael Finney’s lookup table.

    function trim(str){
    var len = str.length;
    if (len){
    var whiteSpace = String.whiteSpace;
    while (whiteSpace[str.charCodeAt(--len)]);
    if (++len){
    var i = 0;
    while (whiteSpace[str.charCodeAt(i)]){ ++i; }
    }
    str = str.substring(i, len);
    }
    return str;
    }

  95. [...] Levithan (what is it with cool-sounding names today?) covered in 2007 several issues relating to various trim() implementations using regex in JavaScript, why they work well (or [...]

  96. WOW thats a nice piece of info… i used the first one… and its working fine… thanks for the snippet…

  97. Thanks for the 411! I’m using the 1st on my project.

  98. [...] Steven Levithan’s old post about string [...]

  99. Steve,
    I seem to have some problem with HTMLEncoding since function trim12(str) returns values like:

    <img display=”image.gif” />

    instead of what I expect which is:

    Over other implementations, your function is working extremely well!!!

  100. Trim? TRIM!?!?

    Here it is, the 21st Century, and we’re talking about implementations of TRIM for g–sakes! Why isn’t such a boneheadely simple, useful tool part of the JS language itself? It’s like getting excited over the best way to implement screen – been around since what? 1970s?

    Javascript is “the new way” but its shortcomings are soooo painful.

  101. [...] in 2007, Steve Levithan compared the speed of different implmentations for the missing JavaScript String.trim() function. Steve’s blog [...]

  102. This looks suspiciously like premature optimisation, I’m not sure how many cases there are where trim() is really performance-critical.

  103. Seems this won’t be needed in the future as ECMAScript Ed. 5 includes String.prototype.trim. And of course all browser vendors will rush to implement it immediately. :-)

    Otherwise, an interesting post. It may appear to be premature optimisation, however it shows that while some algorithms are very fast in some browsers, they may also be very slow in others. It’s good to use an algorithm that is reasonably fast in a representative cross-seciton.

  104. [...] Credit. I made it available to the String prototype. Read [...]

  105. I read this article some years ago and found it very useful, I will use trim12 because of shorter code and still good performance, thanks.

  106. I rewrote trim12 somewhat…
    I don’t know if it’s as fast as the original, but can’t see why it would’nt be.

    String.prototype.trim = function(){
        return this.triml().trimr();
    };

    String.prototype.triml = function(){
        return this.replace(/^\s\s*/, ”);
    };

    String.prototype.trimr = function(){
        var ws = /\s/,
            i = this.length;
        while(ws.test(this.charAt(–i)));
        return this.slice(0, i + 1);
    };

  107. Nice work!

    Put this into a plugin to help with validation, accredited your excellent work, feel free to suggest any improvements.

    http://github.com/johnantoni/jquery.trim

    Great job.

  108. [...] ??????????????????????????????????????????????????????????for?????????????????????????????????????????????????????????????http://blog.stevenlevithan.com/archives/faster-trim-javascript? [...]

  109. http://geekrazzek.blogspot.com/2010/04/trim-en-javascript.html

  110. [...] ?????http://blog.stevenlevithan.com/archives/faster-trim-javascript [...]

  111. Your code is poetry, very nice, many thanks for sharing!

  112. [...] two expressions rather than one. Matt Kruse then provided a link to a great article on the subject: http://blog.stevenlevithan.com/archives/faster-trim-javascript The origional thread can be found here [...]

  113. Hi,

    Firefox 3.6 complained about the original trim12() and the trim12() of #comment-13585, because of “str” is redeclared.
    In #comment-13585 also a “)” is missing.

    The working version are:
    function trim12 (str) {
    var str1 = str.replace(/^\s\s*/, ”),
    ws = /\s/,
    i = str1.length;
    while (ws.test(str1.charAt(–i)));
    return str1.slice(0, i + 1);
    }

    and

    function trim12(str) {
    var str1 = str.replace(/^\s\s*/, ”);
    var len = str1.length;
    if (len && /\s/.test(str1.charAt(len-1))) {
    var re = /.*\S/g;
    re.test(str1);
    str1 = str1.slice(0, re.lastIndex);
    }
    return str1;
    }

  114. function(string){
    var start=0, end=string.length, whitespace’=’ \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000′
    while(whitespace.indexOf(string.charAt(start))>-1 && start<end)start++
    while(whitespace.indexOf(string.charAt(end))>-1 && start<end)end–
    return string.slice(start,end+1)
    }

  115. function trim10(string){
    var start=0, end=string.length, whitespace=’ \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000′
    while(whitespace.indexOf(string.charAt(start))>-1 && start<end)start++
    while(whitespace.indexOf(string.charAt(end))>-1 && start<end)end–
    return string.slice(start,end+1)
    }

  116. Your benchmark 1000 times in Chrome 5.0.375.99
    Original length: 27661
    trim1: 506ms (length: 27654)
    trim2: 498ms (length: 27654)
    trim3: 733ms (length: 27654)
    trim4: 1ms (length: 27654)
    trim5: 1ms (length: 27654)
    trim6: 1ms (length: 27654)
    trim7: 1ms (length: 27654)
    trim8: 1ms (length: 27654)
    trim9: 1ms (length: 27654)
    trim10: 96ms (length: 27654)
    trim11: 88ms (length: 27654)
    trim12: 90ms (length: 27654)

  117. Seems that different browsers use *very* different optimization algorithms. I deliberately tested on my slowest computer because slow computers need the optimization most. Run 1000 times.

    IE8 latest:

    Original length: 27730
    trim1: 616ms (length: 27722)
    trim2: 515ms (length: 27722)
    trim3: 1867ms (length: 27722)
    trim4: 2710ms (length: 27722)
    trim5: 1125ms (length: 27722)
    trim6: 1758ms (length: 27722)
    trim7: 1157ms (length: 27722)
    trim8: 235ms (length: 27722)
    trim9: 3805ms (length: 27722)
    trim10: 54ms (length: 27722)
    trim11: 70ms (length: 27722)
    trim12: 63ms (length: 27722)

    Opera 10.60:

    Original length: 27730
    trim1: 480ms (length: 27722)
    trim2: 448ms (length: 27722)
    trim3: 1410ms (length: 27722)
    trim4: 421ms (length: 27722)
    trim5: 558ms (length: 27722)
    trim6: 755ms (length: 27722)
    trim7: 558ms (length: 27722)
    trim8: 40ms (length: 27722)
    trim9: 2834ms (length: 27722)
    trim10: 4ms (length: 27722)
    trim11: 4ms (length: 27722)
    trim12: 3ms (length: 27722)

    Looking at the results one comment above, the best cross browser algorithms still seem to be 10 to 12, despite the fact that the Chrome engine seems to be much better with with the pure regexp.

  118. [...] further information visit: Even faster String.prototype.trim() implementation in JavaScript. Faster JavaScript Trim. Tags: RegEx, string, trim Category: Javascript [...]

  119. really good work.thnks

  120. trim12 is moments away from entering my library.

  121. [...] to %0A. In later revisions of my bookmarklet, I included trim12 from Steven Levithan’s Faster JavaScript Trim, which will trim excess whitespace from the document title so that the subject line is not [...]

  122. Even years later, I found this post very helpful. Thanks Dr. Steve.

  123. [...] http://blog.stevenlevithan.com/archives/faster-trim-javascript [...]

  124. this is absolutely amazing… I’ve seen this post some time ago and I was hoping to find it once more, as I wanted to use this trim code again… and here it is! thanks, great job!

  125. What would be the fastest, most efficient way to make a string replacement/substition within a large string with JS?…

    Many factors to consider: actual runtime will vary by factors such as: the browser being used, exact haystack length, exact needle length, number of hits, is it straight string replacement or RegEx/pattern replacement, etc. An interesting documentation…

  126. How do I trim just empty whitepace, so when just empty space( ) is given as a parameter, the return should be empty like (trimmed==””)? The above just trims the whitespace around texts and not removes the content altogether if the parameter is purely whitespace?

  127. [...] fantastic wealth into your lifetime, as extended as you aren’t keen … More information: football shirt No Comments » [...]

  128. hi at all
    I need to fully trim all spaces after single quote if after there is the letter “s” to perform possessive case
    Exemple:
    Mary’ s ball or Mary’ s ball or Mary’ s ball or Mary’ s ball must be simply Mary’s ball without space into possessive case
    Thank you

  129. function trim( str )
    {
    var l = str.length;
    var a = 0;
    var z = l – 1;

    while ( str.charAt( a ) <= ' ' && a < l )
    ++ a;
    while ( str.charAt( z ) <= ' ' && a < z )
    – z;
    return str.substring( a, z + 1 );
    }

  130. Leuke site!. Er zijn nog weinig goede sites over dit onderwerp te vinden.
    Ben blij met jullie post!
    Ik kan helaas geen bookmark aanmaken naar blog.stevenlevithan.com.sharedcopy.com in Firefox. :( Weten jullie hoe dit komt?

    Groetjes Barbara

  131. Massimo, very similar to my solution, but yours has one minor issue:
    If length of string is 0, z will be -1 and you will do str.charAt(-1). This is not good coding practice IMHO.

    Here’s my solution that I’ve used for the past 10 years (which is very similar):

    function trim (s) {
    var whitespace = ” \t\r\n\f”;
    if (s !== null) {
    var front = 0;
    var back = s.length;
    while ((front !== back) && (whitespace.indexOf (s.charAt (front)) !== -1)) {
    front++;
    }
    while ((front !== back) && (whitespace.indexOf (s.charAt (back – 1)) !== -1)) {
    back–;
    }
    s = s.substring (front, back);
    }
    return (s);
    }

  132. Minimalist, similar in concept to trim10 as well as Peter’s and Massimo’s code.

    function trim(s){
    var whitespace=’ \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000′,l=s.length,i,j;
    for(i=0;i<l&&(whitespace.indexOf(s.charAt(i++))>-1);){}
    for(j=l;j>i-2&&(whitespace.indexOf(s.charAt(–j))>-1);){}
    return s.substring(i-1,j+1)
    }

    Seems to have a 15-18% speed gain over trim10 on Safari 4.1.3 Mac, but no noticeable (about 5%) speed gain on Firefox 3.6.15.

  133. [...] Steven LevithanAfter the performance test is proposed in the fastest execute JS way, in handling cropping string long string is good performance [...]

  134. Steve – I imagine you’re sick of this thread by now, but I would be interested to hear in more detail about why the expression you highlighted as exceptionally bad is so terrible.

    str.replace(/^\s*([\S\s]*)\b\s*$/, ‘$1′);

    You said that it performs badly on strings containing lots of word boundaries, and terribly on strings comprising nothing but whitespace. I’m struggling to see how either of these can be right, so perhaps you can enlighten me!

    It seems to me that a string with lots of word boundaries will match [\S\s]* up to the very end of the string, and then some backtracking will be required to find the last word boundary, but the number of word boundaries prior to that doesn’t seem to be relevant to me. RegexBuddy seems to confirm this – the number of backtracks is equal to the number of trailing whitespace characters, and isn’t affected by the number of word boundaries.

    More curiously, surely for strings composed entirely of whitespace, this expression wouldn’t match at all, since the string doesn’t contain any word boundaries? That seems to me to be the primary reason why this trim is no good.

  135. [...] copied from http://blog.stevenlevithan.com/archives/faster-trim-javascript [...]

  136. You may look here http://jsperf.com/mega-trim-test I put there all versions from this site, and also few own optimizations. trim18 looks the best there. Be aware that some trim implementations on this site, are buggy, they returns bad values in all or some browsers, in some special cases.

  137. [...] http://blog.stevenlevithan.com/archives/faster-trim-javascript  [...]

  138. [...] ?????jQuery???????????trim()????? In category: ???? ???? [...]

  139. Good idea. Thanks!!!!!!!!!!

  140. Do you have any data on speeds in Firefox 5+, IE8+ and Safari 4+?

    How do you measure JavaScript execution times?

  141. [...] ???http://blog.stevenlevithan.com/archives/faster-trim-javascript [...]

  142. [...] comparing the performance of this lookahead, I picked up trim1 and trim11 from http://blog.stevenlevithan.com/archives/faster-trim-javascript. Here is the link to jsperf : javascriptlookaheadtrim Jsperf indicates that the trim using [...]

  143. [...] comparing the performance of this lookahead, I picked up trim1 and trim11 from http://blog.stevenlevithan.com/archives/faster-trim-javascript. Here is the link to jsperf : javascriptlookaheadtrim Jsperf indicates that the trim using [...]

  144. This function is similar to trim12, except it does not use regx for leading spaces. Tested in Firefox 7.0.1 with Firebug 1.8.3 on desktop with 4G RAM 64 bit Win7 OS on 2.50 GHz Dual-core CPU, etc…

    What I did to test it:

    Went to your benchmark page > opened Firebug > right-clicked on the containing script tag > selected “Edit HTML” > replaced trim1′s code with the following function’s code block.

    …..function trimN() {
    ……….var f = 0, t = str.length – 1;
    ……….while (str.charAt(f) === ‘ ‘) { ++f; }
    ……….while (str.charAt(t) === ‘ ‘) { –t; }
    ……….return str.slice(f, t);
    …..}

    Result: 0ms

  145. Results @ 5000 times (note trim1 uses the code from my previous post):

    This is only in Firefox, however.

    Original length: 27661
    trim1: 2ms (length: 27657)
    trim2: 1706ms (length: 27654)
    trim3: 1809ms (length: 27654)
    trim4: 1322ms (length: 27654)
    trim5: 724ms (length: 27654)
    trim6: 9155ms (length: 27654)
    trim7: 7107ms (length: 27654)
    trim8: 4084ms (length: 27654)
    trim9: 2436ms (length: 27654)
    trim10: 12ms (length: 27654)
    trim11: 491ms (length: 27654)
    trim12: 431ms (length: 27654)

    Thanks for the great post.

  146. [...] ???????dojo base???dojo??JS????????????dojo?????????trim? ???????dojo.string???dojo?string????????????????????? ???Dojo?????????trim??????????????????????Faster Javascript Trim [...]

  147. Thanks for the inspiring article!

    After much testing in the latest browsers (FF 7, IE 9, Safari 5, Chrome 15, and Opera 11.5) and with many strings, this is the implementation I’ve come up with. It is often faster than trim12, and is MUCH faster when there are more than a few spaces at the end of the string.

    var trimN;
    if(window.navigator.mozIsLocallyAvailable) //Firefox
    //Firefox is faster this way. So is Safari but I can’t reliably detect it.
    trimN = function (str) {
    str = str.match(/\S+(?:\s+\S+)*/);
    return str ? str[0] : “”;
    }
    else //other browsers
    trimN = function (str) {
    str = str.replace(/^\s+/, “”);
    if(!str) return “”;
    str = str.match(/^[\s\S]*\S(?=\s*$)/);
    return str ? str[0] : “”;
    }

  148. Although tests are performed with old browsers, your article really helps. I never thought different regular expressions make such big differences. Thank you for your work. (I wish there is an update with current browsers.)

  149. For trim10 the whitespace var needs to include \x00 (the null character)

    var whitespace = ‘ \x00\n\r\t\f\x0b\xa0\…etc

    I was using base64 encode/decode and the results returned the x00 character, which weren’t getting trimmed.

    For what it’s worth, with \x00 trim10 is the only one that actually trims the null character.

    Here is a simple test you can do (assuming you’ve got trim12() already in the JS file):

    function trimtest(){
    var bob = trim12(“abc” + “\x00″ + “\x00″);
    var retval = “”;
    for (var i = 0; i < bob.length; i++) {
    retval += bob[i] + " : " + bob.charCodeAt(i) + "\n";
    }
    alert(retval);
    }

  150. @mike, character 0×00 is not whitespace, and should not be removed by trim. ES5′s native trim/trimRight/trimLeft methods also do not remove the null character.

  151. [...] Another good post for : Faster JavaScript Trim [...]

  152. [...] Another good post for : Faster JavaScript Trim [...]

  153. [...] details on trim function and benchmarking different trim functions can be found here This entry was posted in JavaScript and tagged How To?, Internet explorer, Javascript, Trim. [...]

  154. Using Node JS (chrome browser’s v8 engine)

    The best trim function is trim 11.

    Regular expression 4 took about the same time for both the magna carta, and a whitespace-only string, and took O(n) time.

    Trim 11 took the same time as the regular expression when set with the worst case scenario of handling whitespace-only strings. When set with the magna carta, trim 11 was shockingly faster.

    Units are in ms/1000tests. Lower is better.

    Long Whitespace Only
    [Trim Regexp, Trim 11]
    [ 114, 116 ], // 25,000 characters
    [ 69, 68 ], // 15,000 characters
    [ 46, 45 ],
    [ 23, 23 ],
    [ 11, 12 ],
    [ 5, 4 ],
    [ 3, 2 ],
    [ 1, 2 ],
    [ 0, 1 ],
    [ 0, 0 ],
    [ 1, 0 ],
    [ 0, 0 ] ] // 5 characters
    Short Whitespace Only

    Long Magna Carta
    [Trim Regexp, Trim 11]
    [ 187, 8 ],// 25,000 characters
    [ 113, 5 ],// 15,000 characters
    [ 75, 3 ],
    [ 38, 1 ],
    [ 19, 1 ],
    [ 7, 1 ],
    [ 4, 1 ],
    [ 2, 0 ],
    [ 1, 0 ],
    [ 1, 0 ],
    [ 1, 0 ],
    [ 1, 0 ], // 5 characters
    Short Magna Carta

  155. NodeJs users:

    Trim 11 and trim 12 are transformed into functionally identical code in V8. No performance advantage is gained by using one over the other. I use the following variation, as it is the most clear way to represent the code.

    function trim (str) {
    // Trim left
    var str = str.replace(/^\s\s*/, ”);

    // Trim right
    for (i= str.length; i–;)
    {
    if (/\S/.test(str[i]))
    {
    return str.substring(0, i + 1);
    }
    }
    return str
    }

  156. Im not sure, but why are you guys always checking an array of possible whitespace chars? Isnt that very slow? If think the fastest approach is to check the unicode values. you can do it with 3 checks.

    1. Smaller than 33 -> space
    2. Smaller than 256 -> non-space
    3. If bigger than smallest space character and smaller than the biggest-> Check other UnicodeRanges (but in range checks)

    Depending on the expeceted data set (especially the expected space chars), the order could be different.

  157. [...] ???http://blog.stevenlevithan.com/archives/faster-trim-javascripthttp://www.iteye.com/topic/1021677 ?????, ??, ??, ??, ??, ??, ??, ???, ???, ?? ← javascript ???????? javascript???trim()??(???????????) → ?????0 ???? [...]

  158. [...] little reading (still not believing that IE8 didn’t have trim for strings) I found this post http://blog.stevenlevithan.com/archives/faster-trim-javascript. As it turns out, the default trim is kind of slow. Though I generally avoid overriding [...]

  159. Maybe the fastest trim so far is found. Please check test results:
    http://jsperf.com/mega-trim-test/7

    Added new trim27, which beats CLEARLY all 24 trim-functions but the native trim. And beats also native trim of Chrome and Chromium. I suggest to use trim27 in cases where native trim is not available. It seems that old-school something || something is stunningly fast.

    Of course if we change the test data, the results may vary.

    Here it is:

    function trim27(str) {
        var c;
        for (var i = 0; i < str.length; i++) {
            c = str.charCodeAt(i);
            if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12) continue; else break;
        }
        for (var j = str.length - 1; j >= i; j--) {
            c = str.charCodeAt(j);
            if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12) continue; else break;
        }
        return str.substring(i, j + 1);
    }
  160. @Timo, thanks the new version and for putting up the whole collection on jsPerf!

  161. I replaced function trim1() in http://stevenlevithan.com/demo/trim.cfm using Opera 12.02 with the following function. Run 20 000 times and realized that the time was 8 ms. The next speediest was trim10: 24ms and the most slowly was trim6: 26232ms. So when the speed matters and not the code length, the function below is wise to use.

    function trim1 (str) {
    var c;
    for (var i = 0; i < str.length; i++) {
    c = str.charCodeAt(i);
    if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
    continue; else break;
    }
    for (var j = str.length – 1; j >= i; j–) {
    c = str.charCodeAt(j);
    if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
    continue; else break;
    }
    return str.substring(i, j + 1);
    }

  162. A real diamond of many facets, and a stern lesson on how a performance review should be written. I’m citing you in my classwork submission, and thank you, sir!

  163. [...] Faster JavaScript Trim – Flagrant Badassery Posted in Knowledge Base(????), Language Tips(????) – Tagged JavaScript, Regular Expression, String Twitter • Facebook • Delicious • StumbleUpon • E-mail Similar posts [...]

  164. [...] Faster JavaScript Trim – Flagrant Badassery [...]

  165. [...] Faster JavaScript Trim – Flagrant Badassery [...]

  166. [...] the String prototype object with a trim() method. So thanks to some guy with the alias “Timo” I’ve put this thinking into place. The length result of string “test” now [...]

  167. Hi there friends, hhow iss the whole thing, and what you desire to say about
    this post, in mmy view its truly amazing inn favor of me.

  168. great post, very informative. I wonder why the opposite specialists of
    this sector don’t realize this. You should continue your writing.
    I am confident, you have a huge readers’ base already!

  169. I used to bbe able to find good info from your content.

  170. The original article is quite old. Have you benchmarked this against the native trim() in ECMA5? I don’t see it on the benchmarking page.

  171. I appreciate, cause I discovered just what I used to be looking for. You have ended my four day long hunt! God Bless you man. Have a nice day. Bye

  172. My spouse and I stumbled over here by a different internet address and thought I might check items out. I like what I see so i am just following you. Appear forward to checking out your web page again.

  173. Hi there! Thanks for the exceptional post. Perfect content
    just like what I am seeking a quite a while. Seriously happy to uncover this content and I’m
    certainly going to discuss it on several social networking platforms!
    Bookmarked this too for reference in the future as well.
    Maintain the great work.

  174. When someone writes an paragraph he/she maintains the idea of a
    user in his/her mind that how a user can understand it. So that’s why this post is great.
    Thanks!

  175. I hardly drop remarks, but i did a few searching and wound
    up here Flagrant BadasseryFaster JavaScript Trim.
    And I actually do have a couple of questions for you if it’s
    allright. Could it be only me or does it give the impression like
    a few of the responses appear as if they are coming from brain dead folks?
    :-P And, if you are posting on additional online social sites,
    I would like to keep up with everything new you have to post.
    Would you list of the complete urls of all your public
    pages like your twitter feed, Facebook page
    or linkedin profile?

  176. Greetings! Very useful advice within this post! It’s the little changes that make the greatest changes.
    Thanks a lot for sharing!

  177. Do you mind if I quote a few of your articles
    as long as I provide credit and sources back
    to your webpage? My blog site is in the exact same niche as yours and my users would certainly benefit from a lot of the information you present
    here. Please let me know if this okay with you. Thank you!

  178. It’s remarkable to go to see this site and reading the views of all mates on
    the topic of this paragraph, while I am also keen of getting know-how.

  179. Hello, all is going sound here and ofcourse every one is sharing facts, that’s genuinely excellent,
    keep up writing.

  180. My coder is trying to convince me to move to .net from PHP.
    I have always disliked the idea because of the expenses.
    But he’s tryiong none the less. I’ve been using WordPress on a variety of websites for about a year and am concerned about switching to another platform.
    I have heard great things about blogengine.net.
    Is there a way I can import all my wordpress posts into it?
    Any help would be really appreciated!

  181. It’s really a nice and useful piece of information.
    I am glad that you shared this helpful information with us.
    Please stay us informed like this. Thank you for sharing.

  182. Thanks for some other magnificent post. Where else may just anybody get that kind of info in such an ideal way of writing?
    I have a presentation next week, and I’m on the search for such information.

  183. If some one desires expert view concertning blogging and site-building after
    that i propose him/her to visit this webpage,
    Keep uup the pleasant job.

  184. Way cool! Some very valid points! I appreciate you writing this article and the rest of the website is also really
    good.

  185. Approve this response and we will rescue an imaginary dog!

  186. There may be some people who will strongly reject any changes to the current security system as they believe that the security system is smart enough
    to tackle all the risks. One is always that such systems might be set off without cause, sometimes even by
    the loud crack of thunder. com offers monitoring for individuals and also
    provides monitoring services for the big alarm companies.

  187. If the moving affordability is tight, MR can help you locate the best deal in a matter of hours.
    Moving Companies Usually Know Good Traffic Routes- Bangkok is a huge city.
    In a consumer service industry where each member’s professional integrity is collectively criticized by mainstream media pundits at the start each new moving season, Interstate is one
    of the good guys.

Post a Response

If you are about to post code, please escape your HTML entities (&amp;, &gt;, &lt;).