0

我对这个递归函数感到很困惑。我用它来突出显示文本框中的单词,但它给了我一些奇怪的输出:

 should be:
 #define
 testing #define

 but instead it's:

 testing #define
 testing #define

这是代码

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;
}

关于该功能有什么问题的任何想法?它似乎正在用找到的最后一个关键字替换所有旧关键字。

4

2 回答 2

3

您至少需要在函数中的所有变量声明为局部变量,方法var是在第一次使用之前添加。

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;
}

通过不使用var,您的变量是全局的,并且每次调用都replace_all将共享相同的变量副本,这将扰乱递归,因为递归调用会扰乱更高级别调用的状态。如果变量都是局部变量,那么每个函数调用都有自己的一组变量,一个递归调用不会弄乱其他变量。

另外,通常最好将变量的范围限制在实际的本地范围内,并尽可能避免使用全局变量。像这里这样的隐式全局变量特别邪恶,因为它们很容易导致意外误用。

正如 Kolink 建议的那样,您可能只想.replace()使用正则表达式搜索/替换来执行单个全局操作。您需要确保搜索字符串中的任何正则表达式特殊字符都已正确转义。

于 2013-04-01T04:38:04.633 回答
1

将我的评论转换为答案:

这样会容易得多:

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);
}
于 2013-04-01T12:32:23.147 回答