鉴于此功能:
function doThing(values,things){
var thatRegex = /^http:\/\//i; // is this created once or on every execution?
if (values.match(thatRegex)) return values;
return things;
}
Run Code Online (Sandbox Code Playgroud)
JavaScript引擎多久创建一次正则表达式?每次执行一次或每页加载/脚本解析一次?
为了防止不必要的答案或评论,我个人赞成将正则表达式放在函数之外,而不是在函数内部.问题是关于语言的行为,因为我不知道在哪里查看,或者这是引擎问题.
我被提醒我没有提到这将在循环中使用.我很抱歉:
var newList = [];
foreach(item1 in ListOfItems1){
foreach(item2 in ListOfItems2){
newList.push(doThing(item1, item2));
}
}
Run Code Online (Sandbox Code Playgroud)
因此,假设它将在循环中多次使用,那么在函数外部定义正则表达式是有意义的,但这就是理念.
另请注意,脚本相当通用化,目的只是检查正则表达式创建的行为和成本
Bol*_*ock 13
来自Mozilla的正则表达式JavaScript指南:
正则表达式文字在评估脚本时提供正则表达式的编译.当正则表达式保持不变时,使用它来获得更好的性能.
从ECMA-262规范,§7.8.5正则表达式文字:
正则表达式文字是一个输入元素,每次计算文字时都会转换为RegExp对象(见15.10).
换句话说,当它被评估为首先解析脚本时,它被编译一次.
值得一提的还有,从ES5规范,这两个字符串将编译到两个不同的实例中RegExp
,即使文字本身是相同的.因此,如果给定的文字在您的脚本中出现两次,它将被编译两次,到两个不同的实例:
程序中的两个正则表达式文字计算为正则表达式对象,即使两个文字的内容相同,它们也绝不会相互比较为===.
...
...每次计算文字时,都会创建一个新对象,就像表达式一样
new RegExp(Pattern, Flags)
,RegExp是具有该名称的标准内置构造函数.
提供的答案没有清楚地区分场景背后的两个不同进程:regexp编译和regexp对象创建在命中regexp对象创建表达式时.
是的,使用regexp文字语法,您可以获得一次正则表达式编译的性能优势.
但是如果您的代码在ES5 +环境中执行,那么每次代码路径进入doThing()
示例中的函数时,它实际上都会创建一个新RegExp
对象,而无需一次又一次地编译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"
Run Code Online (Sandbox Code Playgroud)
为了从实际数字的角度说明上述陈述,请查看此jsperf中测试storedRegExp
与inlineRegExp
测试之间的性能差异.
storedRegExp
跨浏览器的速度比inlineRegExp
- RegExp
每次创建(和垃圾收集)新对象的开销要快5到20% .
结论:
如果你大量使用你的文字正则表达式,考虑将它们缓存在需要它们的范围之外,这样它们不仅可以被编译一次,而且它们的实际正则表达式对象也会被创建一次.
每次调用函数时都会编译正则表达式,如果它不是字面形式的话.
由于您以字面形式包含它,因此您无需担心.
这是来自websina.com的报价:
正则表达式文字在评估脚本时提供正则表达式的编译.当正则表达式保持不变时,使用它来获得更好的性能.
调用RegExp对象的构造函数,如下所示:
re = new RegExp("ab+c")
使用构造函数提供正则表达式的运行时编译.当您知道正则表达式模式将要更改时,或者您不知道该模式并从其他源(例如用户输入)获取该模式时,请使用构造函数.
javascript中有两个“正则表达式”类型的对象。 正则表达式实例和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'
Run Code Online (Sandbox Code Playgroud)
使用语法1时,在加载脚本时会编译实际模式
使用之前,pattern参数将编译为内部格式。对于语法1,将在加载脚本时编译模式。对于语法2,模式是在使用之前或在调用compile方法时进行编译的。
但是您仍然可以在每个方法调用中获得不同的正则表达式实例。在Chrome和Firefox中测试
function testregex() {
var localreg = /abc/;
if (testregex.reg != null){
alert(localreg === testregex.reg);
};
testregex.reg = localreg;
}
testregex();
testregex();
Run Code Online (Sandbox Code Playgroud)
这非常少,但是如果您只需要一个正则表达式,则最安全的做法是仅在函数外部创建一个实例
归档时间: |
|
查看次数: |
2211 次 |
最近记录: |