2012-06-13 54 views
12

可能重复:
Interesting test of Javascript RegExp
Regular expression test can't decide between true and false (JavaScript)为什么相同的RegExp行为有所不同?

Example of issue。当内联运行时,结果如我所料。但是,当作为变量存储时,它将跳过中间跨度元素。

// Inline RegExp 
function getToggleClasses() { 
    var toggler = [], 
     elements = document.getElementsByTagName("*"), 
     i=0, 
     len = elements.length; 

    for (i; i < len; i++) { 
    if (/toggler/g.test(elements[i].className)) { 
     toggler.push(elements[i]); 
    } 
    } 

    document.getElementById('results').innerHTML += "<br />Inline: " + toggler.length; 
} 

// Variable 
function getToggleClasses2() { 
    var toggler = [], 
     elements = document.getElementsByTagName("*"), 
     tester = /toggler/g, 
     i=0, 
     len = elements.length; 

    for (i; i < len; i++) { 
    if (tester.test(elements[i].className)) { 
     toggler.push(elements[i]); 
    } 
    } 

    document.getElementById('results').innerHTML += "<br />Variable: " + toggler.length; 
} 
​ 

标记:

<span class="toggler">A</span> 
<span class="toggler">B</span> 
<span class="toggler">C</span> 

鉴于: 我明白没有理由要使用正规做这种比较,我也明白了很大的库如jQuery的怎么样了。我也知道在这种情况下不需要g

我不明白为什么这两种方法应该返回不同的结果。

+0

这只是个人偏好,但我认为它会提高清晰度,使括号围绕在正文上调用函数时具有标志的正则表达式文字。 – JAB

+1

@apillers,你是对的。你寻找什么来找到那些?我找不到要搜索的内容以获得我之前的结果。 – Joe

+0

我骗了一点,并搜索'[javascript]正则表达式测试lastindex' - 我确信这个问题之前已经被问过,我知道答案会包含文字'lastIndex'。这是一个很好的例子,表明存在重复问题并不一定表明提问者是疏忽的;你已经提出了一个好的问题来解决一个难以搜索的问题。 – apsillers

回答

9

RegExp实例是有状态,所以重用他们可能会导致意外的行为。在这种情况下,这是因为实例是global,这意味着:

正则表达式应该针对字符串中的所有可能匹配进行测试。

但是,这不是使用g造成的唯一区别。 From RegExp.test @ MDN

exec(或与之结合),test呼吁同全球正则表达式的情况下多次将提前超越了上一次的比赛。


Remove the g flag,或set lastIndex to 0(感谢,@zzzzBov)。

+3

或设置'lastIndex'为'0' ... – zzzzBov

+0

@zzzzBov好点,编辑。 –

3

/g不是需要和不应该在这种情况下使用。

这些情况下的行为不同,因为在“内联”情况下,循环的每次迭代都会重新创建正则表达式对象。在变量中创建一次,并在循环迭代之间保持其状态(lastIndex)。

移动VAR进入循环,你会得到相同的结果:

// Variable 
function getToggleClasses2() { 
    var toggler = [], 
     elements = document.getElementsByTagName("*"), 
     i=0, 
     len = elements.length; 

    for (i; i < len; i++) { 
    var tester = /toggler/g; 
    if (tester.test(elements[i].className)) { 
     toggler.push(elements[i]); 
    } 
    } 

    document.getElementById('results').innerHTML += "<br />Variable: " + toggler.length; 
} 
+1

是的,我明白了。但是,为什么我很好奇知道。因为'/toggler/g.test('toggler'); // true' – Joe

+1

@Joe,解释。 – Qtax

+1

@Joe,你在问题中写道*“我也知道'g'是需要的”*,这就是为什么我声明它不是。 – Qtax

1

正则表达式维护一个名为lastIndex的变量,它是开始下一个搜索的索引。从MDN

exec(或与之结合),test呼吁同全球正则表达式的情况下多次将提前超越了上一次的比赛。

当你定义为每次迭代内嵌正则表达式,状态丢失,lastIndex始终为0,因为你每次有一个新的正则表达式。如果将正则表达式保存为可变,则lastIndex将保存为最后一次匹配的结束位置,在这种情况下会导致在下一个字符串结尾处开始下一个搜索,导致匹配失败。当第三次比较出现时,lastIndex已被重置为0,因为正则表达式知道它上次没有结果。

相关问题