12

可能重复:
Javascript RegExp
正则表达式测试的有趣测试无法决定真假(JavaScript)

问题示例。当内联运行时,结果与我预期的一样。但是当存储为变量时,它会跳过中间跨度元素。

// 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>

Given : 我知道没有理由使用 RegExp 进行这种比较,而且我也了解 jQuery 等库有多么出色。我也知道g在这种情况下不需要。

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

4

3 回答 3

9

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

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

然而,这并不是使用 引起的唯一区别g来自RegExp.test@MDN

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


删除g标志,或设置lastIndex0(感谢@zzzzBov

于 2012-06-13T19:34:54.017 回答
3

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

这些情况下的行为不同,因为在“内联”情况下,正则表达式对象在循环的每次迭代中都会重新创建。While in 变量创建一次,并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;
}
于 2012-06-13T19:33:03.300 回答
1

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

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

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

于 2012-06-13T19:42:00.620 回答