鉴于此功能:
function doThing(values,things){
var thatRegex = /^http:\/\//i; // is this created once or on every execution?
if (values.match(thatRegex)) return values;
return things;
}
JavaScript引擎多久创建一次正则表达式?每次执行一次或每页一次加载/脚本解析?
为了防止不必要的回答或评论,我个人倾向于将正则表达式置于函数之外,而不是在函数内部。问题是关于语言的行为,因为我不知道在哪里查看,或者这是引擎问题。
我被提醒我没有提到这将在循环中使用。道歉:
var newList = [];
foreach(item1 in ListOfItems1){
foreach(item2 in ListOfItems2){
newList.push(doThing(item1, item2));
}
}
因此,假设它将在循环中多次使用,那么在函数外部定义正则表达式是有意义的,但这就是理念。
还注意到脚本是相当通用化的,目的只是检查正则表达式创建的行为和成本
答案 0 :(得分:13)
来自正则表达式的Mozilla's JavaScript Guide:
正则表达式文字在评估脚本时提供正则表达式的编译。当正则表达式保持不变时,请使用它以获得更好的性能。
来自ECMA-262 spec,§7.8.5正则表达式文字:
正则表达式文字是一个输入元素,每次评估文字时都会转换为RegExp对象(见15.10)。
换句话说,当它被评估为首先解析脚本时,它被编译一次。
值得注意的是,从ES5规范来看,两个文字将编译为 RegExp
的两个不同实例,即使文字本身是相同。因此,如果给定的文字在您的脚本中出现两次,它将被编译两次,到两个不同的实例:
程序中的两个正则表达式文字计算为正则表达式对象,即使两个文字的内容相同,也不会相互比较为===。
...
...每次计算文字时,都会创建一个新对象,就像表达式
new RegExp(Pattern, Flags)
一样,其中RegExp是具有该名称的标准内置构造函数。
答案 1 :(得分:6)
提供的答案并没有清楚地区分幕后的两个不同过程:正则表达式编译和正则表达式对象创建,同时点击regexp对象创建表达式。
是的,使用regexp文字语法,您可以获得一次正则表达式编译的性能优势。
但是如果您的代码在ES5 +环境中执行,每次代码路径都进入示例中的doThing()
函数时,它实际上会创建一个新的RegExp
对象,但是,无需一次又一次地编译正则表达式。
在ES5中,每当代码路径到达通过文字创建正则表达式的表达式时,文字语法都会生成一个新的RegExp
对象:
function getRE() {
var re = /[a-z]/;
re.foo = "bar";
return re;
}
var reg = getRE(),
re2 = getRE();
console.log(reg === re2); // false
reg.foo = "baz";
console.log(re2.foo); // "bar"
要从实际数字的角度说明上述陈述,请查看此jsperf中storedRegExp
和inlineRegExp
次测试之间的效果差异。
storedRegExp
比inlineRegExp
快5到20% - 每次创建(和垃圾回收)新RegExp
对象的开销。
<强> Conslusion:强>
如果您正在大量使用文字正则表达式,请考虑将它们缓存在需要它们的范围之外,这样它们不仅可以编译一次,而且它们的实际正则表达式对象也会被创建一次。
答案 2 :(得分:5)
每次调用函数时都会编译正则表达式,如果它不是字面形式。
由于您以字面形式包含它,因此您无需担心。
以下是websina.com的引用:
正则表达式文字在评估脚本时提供正则表达式的编译。当正则表达式保持不变时,使用它来获得更好的性能。
调用RegExp对象的构造函数,如下所示:
re = new RegExp("ab+c")
使用构造函数提供正则表达式的运行时编译。当您知道正则表达式模式将要更改时,或者您不知道该模式并从其他源(例如用户输入)获取该模式时,请使用构造函数。
答案 3 :(得分:5)
javascript中有两个“正则表达式”类型对象。 Regular expression instances和RegExp对象。
此外,有两种方法可以创建正则表达式实例:
每次都会创建新的正则表达式实例。
但是只有一个全局的RegExp对象。
var input = 'abcdef';
var r1 = /(abc)/;
var r2 = /(def)/;
r1.exec(input);
alert(RegExp.$1); //outputs 'abc'
r2.exec(input);
alert(RegExp.$1); //outputs 'def'
在使用语法1
时加载脚本时编译实际模式模式参数在使用前编译为内部格式。对于语法1,在加载脚本时编译模式。对于语法2,模式在使用之前编译,或者在调用编译方法时编译。
但是你仍然可以在每个方法调用时获得不同的正则表达式实例。在chrome vs firefox中测试
function testregex() {
var localreg = /abc/;
if (testregex.reg != null){
alert(localreg === testregex.reg);
};
testregex.reg = localreg;
}
testregex();
testregex();
这是非常小的开销,但是如果你想要一个正则表达式,最安全的只是在你的函数中创建一个 实例