JavaScript重新编译函数中regex文本的频率
How often does JavaScript recompile regex literals in functions?
给定此函数:
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引擎必须多久创建一次正则表达式?每次执行一次还是每次页面加载/脚本解析一次?
为了避免不必要的回答或评论,我个人赞成将regex放在函数之外,而不是放在函数内部。问题是关于语言的行为,因为我不确定在哪里查找,或者这是否是引擎问题。
编辑:
有人提醒我,我没有提到这将被循环使用。抱歉:
var newList = [];
foreach(item1 in ListOfItems1){
foreach(item2 in ListOfItems2){
newList.push(doThing(item1, item2));
}
}
因此,考虑到它将在循环中被多次使用,在函数之外定义正则表达式是有意义的,但这就是想法。
还请注意,该脚本是相当通用的,目的是只检查正则表达式创建的行为和成本<>>
来自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"
为了从实际数字的角度说明上述语句,请查看本jsperf中storedRegExp
和inlineRegExp
测试之间的性能差异。
storedRegExp
在浏览器中的速度将比inlineRegExp
快5-20%,这是每次创建(和垃圾收集)新RegExp
对象的开销。
共谋:
如果您大量使用文字regexp,请考虑将它们缓存在需要它们的范围之外,这样它们不仅可以编译一次,而且还可以为它们创建一次实际的regexp对象。
javascript中有两个"正则表达式"类型的对象。正则表达式实例和RegExp对象。
此外,有两种方法可以创建正则表达式实例:
- 使用/regex/语法和
- 使用新的RegExp("Regx")
每一次都会创建新的正则表达式实例。
但是,只有一个全局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,模式是在使用之前编译的,或者在调用编译方法时编译的。
但是您仍然可以在每次方法调用时获得不同的正则表达式实例。铬与萤火虫的测试
function testregex() {
var localreg = /abc/;
if (testregex.reg != null){
alert(localreg === testregex.reg);
};
testregex.reg = localreg;
}
testregex();
testregex();
这是非常小的开销,但如果您只想要一个正则表达式,那么最安全的做法是只在函数
如果函数不是字面形式的,则每次调用函数时都会编译正则表达式
既然你是以字面的形式包含它,你就没有什么可担心的了。
以下是来自websina.com的一句话:
正则表达式文字在计算脚本时提供正则表达式的编译。当正则表达式保持不变时,请使用此选项以获得更好的性能。
调用RegExp对象的构造函数,如下所示:
re = new RegExp("ab+c")
使用构造函数函数可以在运行时编译正则表达式。当您知道正则表达式模式将要更改,或者您不知道该模式并且正在从其他来源(如用户输入)获取该模式时,请使用构造函数。
- Regex有助于突出显示html中匹配文本的角度过滤器
- jQuery regex从文本链接-添加不需要的域到链接
- 如何使用JavaScript Regex替换字符串中双引号之间的文本
- 使用regex从css文件中获取所有类(以文本形式)
- 文本区域angular的regex验证
- 如何使用RegEx转换文本中的表情符号
- jQuery:如何将RegEx匹配的纯文本包装在锚标记中
- Regex Groups-选择电子邮件地址前的文本
- 在javascript中使用regex只选择标记之间的文本
- regex替换元素文本
- 为什么RegEx输出转义文本而不是HTML
- 用JavaScript和Regex校对文本
- Javascript Regex exec 在向搜索文本添加属性/引号后冻结
- Javascript Regex - 只影响非 html 代码?(即文本)
- 使用 jQuery/JavaScript 使用 Regex 解析文本
- 文本框 (Asp.net) 值,具有 3 个小数位,由 Javascript - Regex 处理
- Javascript Regex 来匹配有界文本
- JavaScript重新编译函数中regex文本的频率
- 使用RegEx文本框OnKeyPress不能按Tab键在键盘上
- regex文本模式与多个单词匹配