为什么相同的RegExp表现不同?

时间:2012-06-13 19:25:45

标签: javascript regex

  

可能重复:
  Interesting test of Javascript RegExp
  Regular expression test can't decide between true and false (JavaScript)

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>

鉴于: 我理解没有理由使用RegExp来进行这种比较,我也理解jQuery这样的库很棒。我也知道在这种情况下不需要g

我无法理解为什么这两种方法应该返回不同的结果。

3 个答案:

答案 0 :(得分:9)

RegExp个实例是有状态的,因此重用它们会导致意外行为。在这种特殊情况下,这是因为实例是global,意思是:

  

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

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

  

exec(或与之结合使用)一样,在同一个全局正则表达式实例上多次调用的test将超过上一个匹配。


Remove the g flagset lastIndex to 0(谢谢,@zzzzBov)。

答案 1 :(得分: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;
}

答案 2 :(得分:1)

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

  

exec(或与之结合使用)一样,在同一个全局正则表达式实例上多次调用的test将超过上一个匹配。

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