Javascript ReplaceAll

Posted: Tuesday March 27th, 2012 in Javascript, Snippet

I always used to copy a method to simulate a replaceAll with the javascript’s prototype, never thinking about speed. Now I decided to go and create a method by myself that do this and also allows you to ignore the case. The only bad thing (or not) is that you can’t use regex, just regular strings =(.
The example below uses all the possible stuff I could to create a faster and compact replaceAll method:

/**
 * ReplaceAll by Fagner Brack (MIT Licensed)
 * Replaces all occurrences of a substring in a string
 */
String.prototype.replaceAll = function( token, newToken, ignoreCase ) {
    var _token;
    var str = this + "";
    var i = -1;
    
    if ( typeof token === "string" ) {
        
        if ( ignoreCase ) {
            
            _token = token.toLowerCase();
            
            while( (
                i = str.toLowerCase().indexOf(
                    token, i >= 0 ? i + newToken.length : 0
                ) ) !== -1
            ) {
                str = str.substring( 0, i ) +
                    newToken +
                    str.substring( i + token.length );
            }
            
        } else {
            return this.split( token ).join( newToken );
        }
        
    }
return str;
};

How to use:

var str = "My house is clean... so clean... Clean";
var _str = "There are 15 sheeps in the 2 ships transporting 14 chips";
var str1 = str.replaceAll("clean", "dirty"); //"My house is dirty... so dirty... Clean"
var str2 = str.replaceAll("clean", "dirty", true); //"My house is dirty... so dirty... dirty"
var str3 = str.replaceAll("clean", "dirty", false); //"My house is dirty... so dirty... Clean"
var str4 = str.replaceAll(" clean", "", true); //"My house is... so..."
var str5 = str.replaceAll(undefined, "nothing"); //"My house is clean... so clean... Clean"
var str6 = str.replaceAll("nothing", undefined); //"My house is clean... so clean... Clean"
var str7 = str.replaceAll(); //"My house is clean... so clean... Clean"
var str8 = str.replaceAll("clean", 0); //"My house is 0... so 0... Clean", "Passing number on newToken, consider it as string"
var str9 = _str.replaceAll(15, "nothing"); //"There are 15 sheeps in the 2 ships transporting 14 chips"

Most of the times I used to copy the concept below:

   while(str.indexOf(token) !== -1) {
      str.replace(token, newToken);
    }

But the major problem of this method is the recursivity. Let’s say you want to do the following:

"A str here".replaceAll("str", "string");

KABOOM, infinite loop and stucked browser. In the replaceAll above this kind of behavior do not occurs

And I saw already a lot of REGEX using normal replace like replace(new RegExp(“token”, “gi”), “newToken”), but it takes toooooo long.

UPDATE:
Looks like this.split(token).join(newToken) works better and is faster for a non ignoreCase situation, so I updated the code (needs to find a way to use native methods ignoring the case =()

Comments
  1. Gustavo says:

    Curti o seu código, e copiei ao embalo de Tarja! Mas mudei o fim colocando um return typeof token para o caso de dar erro eu saber que raio de token eu mandei pra lá.

    • Fagner Martins Brack says:

      Opa \,,/
      o replaceAll não modifica a string original ele retorna a string modificada.
      Se você mudar o return o código não surtirá efeito.

      Para verificar o output do token eu recomendo usar a ferramenta web developer do navegador que vc está testando, você pode usar o console.log fazendo uma checkagem assim:

      if(window.console && window.console.log) {
      window.console.log(typeof token);
      }

  2. jSang says:

    When ignoreCase is true, you should use ‘_token’ instead’ of ‘token’ within the while loop.

    • Fagner Martins Brack says:

      Actually it doesn’t matter if I use _token or token, both of them will have the same length. As a matter of design “token” is much more intuitive than “_token” cause the previous one is used just as a temporary var to check the lowercase of the original.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>