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

Javascript
JS 文件本身编码转换 图文教程
jQuery Ajax之$.get()方法和$.post()方法
jQuery Ajax之load()方法
JavaScript 核心参考教程 内置对象
JavaScript 核心参考教程 RegExp对象
javascript hashtable实现代码
百度留言本js 大家可以参考下
javascript 判断某年某月有多少天的实现代码 推荐
让iframe子窗体取父窗体地址栏参数(querystring)
jquery pagination插件实现无刷新分页代码
jQuery与javascript对照学习 获取父子前后元素 实现代码
通用javascript脚本函数库 方便开发
JQuery 绑定事件时传递参数的实现方法
支持IE,Firefox的javascript 日历控件
javascript 变速加数功能实现代码
extjs 学习笔记(一) 一些基础知识
extjs 学习笔记(二) Ext.Element类
Jquery 学习笔记(一)
一些技巧性实用js代码小结
jquery 常用操作整理 基础入门篇

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-12   浏览: 255 ::
收藏到网摘: 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 全选 提示:你可先修改部分代码,再按运行]