为什么'g'标志会改变JavaScript正则表达式的结果?

Cho*_*Lee 8 javascript regex

考虑:

var reg = new RegExp("^19[-\\d]*","g");
reg.test('1973-02-01') // true
reg.test('1973-01-01') // false
Run Code Online (Sandbox Code Playgroud)

为什么第三行会返回false?如果我删除"g"标志,则返回true.

T.J*_*der 15

在JavaScript中,正则表达式对象具有状态.当g标志("全局")应用于它们时,这很重要,有时以奇怪的方式应用.此状态是上次匹配发生的索引,即正则表达式的.lastIndex属性.当您再次呼叫exectest使用相同的正则表达式对象时,它会从它停止的位置开始拾取.

在你的例子中发生的是第二次调用,它在最后一次停止的地方拾取,所以它看起来是在字符串中的第10个字符之后开始 - 并且在那里找不到匹配,因为那里没有文本所有(即使有,^断言也不匹配).

如果我们查看lastIndex房产,我们可以看到发生了什么:

var reg = new RegExp("^19[-\\d]*","g");
snippet.log("Before first test: " + reg.lastIndex);
snippet.log(reg.test('1973-02-01')); //return true
snippet.log("Before second test: " + reg.lastIndex);
snippet.log(reg.test('1973-01-01')); //return false
snippet.log("After second test: " + reg.lastIndex);
Run Code Online (Sandbox Code Playgroud)
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Run Code Online (Sandbox Code Playgroud)

如果没有该g标志,则正则表达式对象不会保留任何状态,并且每次从字符串的开头开始:

var reg = new RegExp("^19[-\\d]*");
snippet.log("Before first test: " + reg.lastIndex);
snippet.log(reg.test('1973-02-01')); //return true
snippet.log("Before second test: " + reg.lastIndex);
snippet.log(reg.test('1973-01-01')); //return false
snippet.log("After second test: " + reg.lastIndex);
Run Code Online (Sandbox Code Playgroud)
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Run Code Online (Sandbox Code Playgroud)


旁注:通常,最好使用正则表达式文字而不是使用RegExp构造函数和字符串在JvaScript中编写正则表达式.在你的情况下,那将是

var reg = /^19[-\d]*/g;
// or without the g flag:
var reg = /^19[-\d]*/;
Run Code Online (Sandbox Code Playgroud)

附注2:这是没有多大意义,定义了一个正则表达式^$g,除非你还使用标志m(多行)标志,以改变那些什么意思锚.没有m,他们的意思是"输入的开始(^)或结束($)." 随着m标志,他们的意思是"开始(^)或end( $)的线."

  • 一个好的和全面的答案(像往常一样:-).我会添加一个注释(3),说明如果2个日期字符串相同,则会生成完全相同的输出(例如,两个调用中的''1973-02-01'`) (4认同)