全局字符串替换RegExp不删除所有匹配项

时间:2013-11-08 10:18:02

标签: javascript regex

我正在创建一些小的add / remove / toggle / has类函数,它们都运行得很好,直到我在类上有多个相同类名值的实例。

这是我到目前为止的地方,你会看到我的removeClass Regexp中有'g'标志:

Element.prototype.hasClass = function (className) {
    return new RegExp('(\\s|^)' + className + '(\\s|$)').test(this.className);
};

Element.prototype.addClass = function (className) {
    if (!this.hasClass(className)) {
        this.className += ' ' + className;
    }
};

Element.prototype.removeClass = function (className) {
    if (this.hasClass(className)) {
        this.className = this.className.replace(new RegExp('(\\s|^)' + className + '(\\s|$)', 'g'), '$2');
    }
};

Element.prototype.toggleClass = function (className) {
    if (this.hasClass(className)) {
        this.removeClass(className);
    } else {
        this.addClass(className);
    }
};

起始HTML:

<p class=" james james dean james james james">Hello</p>

渲染时:

<p class=" james dean james">Hello</p>

这是我的工作jsFiddle,如果你检查元素,你可以看到并没有删除所有 james 实例。任何人都能明白我做错了什么吗?提前致谢 :) http://jsfiddle.net/8urPs/

4 个答案:

答案 0 :(得分:1)

您希望类字符串始终被空格包围。一旦匹配空白区域,就无法再次匹配。因此,如果有两个james类彼此相邻并由一个空格分隔,则第一个james将匹配并且窃取白色空间。然后第二个james将不匹配 要解决此问题,请在每个括号后添加*。它代表前面元素的零个或多个

  

新的RegExp('(\ s | ^)'+ className +'(\ s | $)','g')

以下是您的更新小提琴:http://jsfiddle.net/8urPs/1/

更新

根据您对多个空格的评论 - 问题是替换价值。在第一种方法中,我保持不变 - $2。实际上,我们在替换中不需要任何内容​​,因此我们可以简单地将其更改为空字符串

this.className = this.className.replace(new RegExp('(\\s|^)*' + className + '(\\s|$)*', 'g'), '');

这是经过纠正的小提琴:http://jsfiddle.net/8urPs/2/

答案 1 :(得分:0)

表达式重叠时遇到问题。您正在替换james;但是,在james james中,中间空间是共享的,正则表达式与重叠跨度不匹配。

重写为使用单词边界(\b)而不是空格和beg / end,或者使用lookahead,以便不占用该空间。

答案 2 :(得分:0)

这是因为类名之间的空格只能是单个匹配的一部分。要解决此问题,您可以使用正面的外观替换最终捕获组,如下所示:

Element.prototype.removeClass = function (className) {
    if (this.hasClass(className)) {
        this.className = this.className.replace(new RegExp('(\\s|^)' + className + '(?=\\s|$)', 'g'), '');
    }
};

答案 3 :(得分:0)

className之后的空格始终匹配,然后无法再次匹配。使用正向前瞻断言可以帮助您:

this.className = this.className.replace(new RegExp('(\\s|^)' + className + '(?=\\s|$)', 'g'), '');

当您使用?=启动捕获组时,它将作为断言进行处理并且不匹配。

工作样本:http://jsfiddle.net/ah3Ge/