backtracking(回朔) 当NFA发现自己吃多了,一个一个往回吐,边吐边找匹配,这个过程叫做backtracking。由于存在这个过程,在NFA匹配过程中,特别是在编写不合理的正则式匹配过程中,文本被反复扫描,效率损失是不小的。明白这个道理,对于写出高效的正则表达式很有帮助。
定位/分析原因 在解释上面的trim原型方法的时候。经过测试,先不说结果是否正确,有几个方法是可以化解JS NFA引擎的回朔次数的 a. 去掉限定的量词,即改成 代码如下:String.prototype.trim = function () { return this.replace(/^[\s\t ]+|[\s\t ]$/g, ''); }b. 去掉字符串尾匹配。即改成: 代码如下:String.prototype.trim = function () { return this.replace(/^[\s\t ]+/g, ''); } c.加入多行匹配。即改成: 代码如下:String.prototype.trim = function () { return this.replace(/^[\s\t ]+|[\s\t ]+$/mg, ''); }从以上三种改法结合文中开头的NFA资料,我们可以大概的知道trim性能出现问题的原因 量词限定将优先匹配。 量词限定在结尾可能会使JS的正则引擎不停的回朔,出现递归的一个陷阱,这个递归的深度太深。如果字符串更大一点应该会出现栈溢出了。 多行既然能够匹配,而且性能消耗不大。性能上没有任何问题,从一个写这个正则程序的人角度上去看,多行明显比单行要替换的空串多得多。所以第二点的结论应该是对的 改良 首先确定匹配字符串的开始正则是没有任何效率问题的。而匹配结束的时候会出现性能问题,那可以采用正则与传统相结合来改善这个trim性能问题。 例如: // script> [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]