当前位置: 首页 > 图文教程 > 网络编程 > Javascript > trim原型函数看js正则表达式的性能

Javascript
jQuery开发者都需要知道的5个小技巧
Extjs学习笔记之六 面版
Javascript 中的类和闭包
IE6下JS动态设置图片src地址问题
Extjs学习笔记之七 布局
Extjs学习笔记之八 继承和事件基础
Extjs TriggerField在弹出窗口显示不出问题的解决方法
JavaScript中的集合及效率
利用js获取服务器时间的两个简单方法
在html页面上拖放移动标签
了解jQuery技巧来提高你的代码
JavaScript 页面坐标相关知识整理
Javascript UrlDecode函数代码
JQuery 遮罩层实现(mask)实现代码
jQuery 页面 Mask实现代码
Javascript的构造函数和constructor属性
js或css文件后面跟参数的原因说明
将CKfinder整合进CKEditor3.0的新方法
jQuery UI-Draggable 参数集合
jQuery 行级解析读取XML文件(附源码)

Javascript 中的 trim原型函数看js正则表达式的性能


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-12   浏览: 261 ::
收藏到网摘: n/a

如果你看到别人写trim函数是用循环而不用正则表达式来写,请不要取笑,也许,他们就是高手。如果你很自信你的trim函数效率很高,请看完本文再下结论。 一般情况下用正则写法为:
点击运行可以看到效果:
[Ctrl+A 全选 提示:你可先修改部分代码,再按运行]

如果遇到大数据的变长字符串的话就会发现这个是很耗资源的。效率并不高,有的时候甚至无法忍受。
点击运行可以看到效果:
[Ctrl+A 全选 提示:你可先修改部分代码,再按运行]

在解释这个原因的时候想起以前看到master regular expression里面有提到过。NFA和DFA的引擎是有区别的。js/perl/php/java/.net都是NFA引擎。
而DFA与NFA机制上的不同带来5个影响:
1. DFA对于文本串里的每一个字符只需扫描一次,比较快,但特性较少;NFA要翻来覆去吃字符、吐字符,速度慢,但是特性丰富,所以反而应用广泛,当今主要的正则表达式引擎,如Perl、Ruby、Python的re模块、Java和.NET的regex库,都是NFA的。
2. 只有NFA才支持lazy和backreference(后向引用)等特性;
3. NFA急于邀功请赏,所以最左子正则式优先匹配成功,因此偶尔会错过最佳匹配结果;DFA则是“最长的左子正则式优先匹配成功”。
4. NFA缺省采用greedy量词(就是对于/.*/、/\w+/这样的“重复n”次的模式,以贪婪方式进行,尽可能匹配更多字符,直到不得以罢手为止),NFA会优先匹配量词。
5. NFA可能会陷入递归调用的陷阱而表现得性能极差。
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性能问题。
例如:
点击运行可以看到效果:
[Ctrl+A 全选 提示:你可先修改部分代码,再按运行]