0

I'm pretty stumped on this recursive function. I'm using it to highlight words in a text box, but it's giving me some strange output:

 should be:
 #define
 testing #define

 but instead it's:

 testing #define
 testing #define

here's the code

function replace_all( text, old_str, new_str ){

    index_of = text.indexOf( old_str );

    if( index_of != -1 ){

            old_text = text.substring( 0, index_of );
            new_text = text.substring( index_of + old_str.length );

            new_text = replace_all( new_text, old_str, new_str );

            text = old_text + new_str + new_text;
    }
    return text;
}

Any ideas on what's wrong with the function? It seems to be replacing all the old keywords with the last one found.

3
  • 1
    What's wrong with function replace_all(text,ostr,nstr) {return text.replace(new RegExp(ostr,"g"),nstr);}? Commented Apr 1, 2013 at 4:37
  • How are you calling the replace_all function? Commented Apr 1, 2013 at 4:37
  • @Kolink that worked. I've never looked up regular expressions but it seems like that does the job. Commented Apr 1, 2013 at 4:42

2 Answers 2

3

You need to at least declare all your variables in the function as local variables by adding var in front of their first use.

function replace_all( text, old_str, new_str ){

    var index_of = text.indexOf( old_str );

    if( index_of != -1 ){

            var old_text = text.substring( 0, index_of );
            var new_text = text.substring( index_of + old_str.length );

            new_text = replace_all( new_text, old_str, new_str );

            text = old_text + new_str + new_text;
    }
    return text;
}

By not using var, your variables are global and each invocation of replace_all will be sharing the same copies of variables which will mess up the recursion as recursive calls will mess up the state of the higher levels calls. If the variables are all local variables, then each function invocation has it's own set of variables and one recursive call does not mess up the others.

Plus, it is generally always a good idea to limit the scope of your variables to as local a scope as practical and avoid globals whenever possible. Implicit globals variables like you have here are particular evil because they can easily lead to accidental misuse.

As Kolink suggested, you might just want to do a single global .replace() operation using a regex search/replace. You would need to make sure that any regex special characters in the search string were properly escaped though.

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

1 Comment

that makes sense. I thought that was happening but had no idea that was the difference between using var
1

Converting my comment to an answer:

This would be a lot easier like so:

function replace_all(text,old_str,new_str) {
    var old_regex = old_str).replace(/[.\\+*?\[\^\]$(){}=!<>|:-]/g, '\\$&');
    // the above line escapes any characters that may interfere with regex behaviour
    return text.replace(new RegExp(old_regex,"g"),new_str);
}

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.