JS编程建议——38:正确认识正则表达式工作机制

建议38:正确认识正则表达式工作机制
有很多因素影响正则表达式的效率。首先,正则表达式适配的文本千差万别,部分匹配时比完全不匹配所用的时间要长。其次,每种浏览器的正则表达式引擎也有不同的内部优化。要有效使用正则表达式,重要的是理解它们的工作机制。一个正则表达式处理的基本步骤如下:
第1步,编译。在创建了一个正则表达式对象后,浏览器先要检查模板有没有错误,然后将它转换成一个本机代码例程,用于执行匹配工作。如果将正则表达式赋给一个变量,就可以避免重复执行此步骤。
第2步,设置起始位置。当一个正则表达式投入使用时,要先确定目标字符串中开始搜索的位置。它是字符串的起始位置,或者由正则表达式的lastIndex 属性指定,但当它从第4步返回到这里的时候,此位置将位于最后一次尝试起始位置推后一个字符的位置上。
浏览器厂商优化正则表达式引擎的方法:在这一阶段中通过早期预测跳过一些不必要的工作。例如,如果一个正则表达式以^开头,IE和Chrome浏览器通常判断在字符串起始位置上是否能够匹配,进而避免不明智地搜索后续位置。另一个例子是匹配第三个字母是x的字符串,聪明的方法是先找到x,然后再将起始位置回溯两个字符。
第3步,匹配每个正则表达式的字元。正则表达式一旦找好起始位置,将会一个个地扫描目标文本和正则表达式模板。当一个特定字元匹配失败时,正则表达式将试图回溯到扫描之前的位置上,然后进入正则表达式其他可能的路径。
第4步,匹配成功或失败。如果在字符串的当前位置上发现一个完全匹配的字符,那么正则表达式宣布成功。如果正则表达式的所有可能路径都尝试过了,但没有成功匹配,那么正则表达式引擎回到第2步,从字符串的下一个字符重新尝试。只有字符串中的每个字符(以及最后一个字符后面的位置)都经历了这样的过程之后还没有成功匹配,正则表达式才会宣布彻底失败。
牢记这一过程将有助于判别那些影响正则表达式性能问题的类型。

时间: 2024-09-14 13:02:31

JS编程建议——38:正确认识正则表达式工作机制的相关文章

JS编程建议——48:慎用正则表达式修剪字符串

建议48:慎用正则表达式修剪字符串(1)使用两个子表达式修剪字符串去除字符串首尾的空格是一个简单而常见的任务,但到目前为止JavaScript 还没有实现它.正则表达式允许用很少的代码实现一个修剪函数,最好的全面解决方案可能是使用两个子表达式:一个用于去除头部空格,另一个用于去除尾部空格.这样处理简单而快速,特别是处理长字符串时.if(!String.prototype.trim) { String.prototype.trim = function() { return this.replac

JS编程建议——46:提高正则表达式执行效率

建议46:提高正则表达式执行效率(1)关注如何让匹配更快失败正则表达式处理慢往往是因为匹配失败过程慢,而不是匹配成功过程慢.使用正则表达式匹配一个很大字符串的一小部分,情况更为严重,正则表达式匹配失败的位置比匹配成功的位置要多得多.一个修改使正则表达式匹配更快但失败更慢,例如,通过增加所需的回溯次数尝试所有分支的排列组合,这通常是一个失败的修改.(2)正则表达式以简单的.必需的字元开始最理想的情况是,一个正则表达式的起始字元应当尽可能快速地测试并排除明显不匹配的位置.用于此目的好的起始字元通常是

JS编程建议——41:正确使用正则表达式引用

建议41:正确使用正则表达式引用正则表达式在执行匹配运算时会自动把每个分组(子表达式)匹配的文本都存储在一个特殊的地方以备将来使用.这些存储在分组中的特殊值被称为反向引用.反向引用将遵循从左到右的顺序,根据表达式中左括号字符的顺序进行创建和编号.var s = "abcdefghijklmn";var r = /(a(b(c)))/;var a = s.match(r); //["abc", "abc" , "bc" , &q

JS编程建议——42:用好正则表达式静态值

建议42:用好正则表达式静态值正则表达式的静态属性比较特殊,有两个名字:长名(全称)和短名(简称,以美元符号开头表示),详细说明见表2.1.表2.1 RegExp的静态属性长名 短名 说明input $_ 最后用于匹配的字符串,即传递给exec()或test()方法的字符串lastMatch $& 最后匹配的字符lastParen $+ 最后匹配的分组leftContext $` 在上次匹配之前的子字符串multiline $* 用于指定是否所有表达式都使用多行模式的布尔值rightContex

JS编程建议——47:避免使用正则表达式的场景

建议47:避免使用正则表达式的场景正则表达式匹配速度是非常快的.然而,当只搜索文字字符串时正则匹配经常会显得多余,尤其当事先知道了字符串的哪一部分将要被测试时.例如,要检查一个字符串是不是以分号结束,可以使用:endsWithSemicolon = /;$/.test(str);当前没有哪个浏览器"聪明"到这个程度,能够意识到这个正则表达式只能匹配字符串的末尾.最终它们所做的将是一个一个地测试整个字符串.每当发现了一个分号,正则表达式就前进到下一个字元($),检查它是否匹配字符串的末尾

JS编程建议——40:正确使用正则表达式分组(2)

建议40:正确使用正则表达式分组(2)当然,并不限制在分组后使用星号,还可以使用任意重复类数量词: var r = /(abcdef-?){5}/; // 连续匹配5次子表达式 var r = /(abcdef-?){1,5}/; // 最多匹配5次子表达式 var r = /(abcdef-?){0,}/; // 匹配任意次子表达式 var r = /(abcdef-?)?/; // 最多匹配一次子表达式 var r = /(abcdef-?)+/; // 最小匹配一次子表达式 如果混合使用字

JS编程建议——8:谨慎使用运算符(1)

建议8:谨慎使用运算符(1)1.用===,而不用==JavaScript有两组相等运算符:===和!==.==和!=.===和!==这一组运算符会按照期望的方式工作.如果两个运算数类型一致且拥有相同的值,那么===返回true,而!==返回false.==和!=只有在两个运算数类型一致时才会做出正确的判断,如果两个运算数是不同的类型,会试图强制转换运算数的类型.转换的规则复杂且难以记忆,具体规则如下: '' == '0' // false 0 == '' // true 0 == '0' //

JS编程建议——50:正确检测数组类型

建议50:正确检测数组类型由于数组和对象的数据同源性,导致在JavaScript编程中经常会出现:在必须使用数组时使用了对象,或者在必须使用对象时使用了数组.选用数组或对象的规则很简单:当属性名是小而连续的整数时,应该使用数组,或者当对属性的位置和排列顺序有要求时,应该使用数组.否则,使用对象.JavaScript语言对数组和对象的区别是混乱的.typeof运算符检测数组的类型是"object",这没有什么意义,因此在正确检测数组和对象方面JavaScript没有提供很多的机制.这时可

JS编程建议——65:比较函数的惰性求值与非惰性求值

建议65:比较函数的惰性求值与非惰性求值在JavaScript中,使用函数式风格编程时,应该对于表达式有着深刻的理解,并能够主动使用表达式的连续运算来组织代码.1)在运算元中,除了JavaScript默认的数据类型外,函数也作为一个重要的运算元参与运算.2)在运算符中,除了JavaScript的大量预定义运算符外,函数还作为一个重要的运算符进行计算和组织代码.函数作为运算符参与运算,具有非惰性求值特性.非惰性求值行为自然会对整个程序产生一定的负面影响.先看下面这个示例:var a = 2;fun