我有以下两个js示例代码,一个使用文字regexp,另一个使用RegExp对象:
"use strict";
var re;
// literal regexp
for(var i = 0; i<10; i++)
{
re = /cat/g;
console.log(re.test("catastrophe"));
}
// RegExp constructor
for(var i = 0; i<10;i++)
{
re = new RegExp("cat", "g");
console.log(re.test("catastrophe"));
}
有些books说使用第一个例子“true”应该在每次第二次迭代时打印,因为使用文字表达式只会创建一个RegExp实例。因此循环在第一次运行时找到子串“cat”,而不是从第二次运行继续从哪里继续找不到任何东西。在第三次运行时,它从头开始,依此类推。我已经测试了这个,但似乎在两个例子中我得到了10的数。
你能解释一下为什么会这样吗?
答案 0 :(得分:5)
第3版ECMAScript(JavaScript)规范允许缓存和重用正则表达式文字,包括它们的状态,导致您提到的与您的第一个代码示例相关的“令人惊讶”的行为,当然看起来它应该创建一个新的常规每个循环上的表达式对象。大多数引擎都没有实现文字的缓存,这是一个非常糟糕的想法,第5版规范修复了它。
我相信所有过去用于缓存的现代引擎(主要是SpiderMonkey,Firefox的引擎)都会相应更新。在两个示例中为每次迭代创建一个新的正则表达式。
More in this blog post (right at the end) by Steven Levithan,以及Annex E in the specification的第四段:
7.8.5:正则表达式文字现在每次评估文字时都返回一个唯一的对象。任何测试此类文字值的对象标识或对共享副作用敏感的程序都可以检测到此更改。
答案 1 :(得分:0)
在这两种情况下,您每次通过for
循环创建一个新的RegExp。声明RegExp的方式无关紧要 - 每次循环迭代时它仍然会创建一个新的。因此,你会得到同样的行为。
现在,如果在re
循环之前初始化for
变量,由于同一个RegExp对象的持久性以及它如何使用g
标志,您将获得不同的行为