msgbartop
PHP源码分析,Zend引擎分析,Web相关技术研究,Web技术分享–左手代码 右手诗
msgbarbottom

27 Sep 09 关于Javascript的俩个有趣的探讨

首先祝贺在经历了几乎一天的等待以后. 我的空间商终于把服务器迁到了电信机房, 外加网通CDN加速.

关于事件处理函数引用的一个佐证

之前, 我在分析Javascript的This关键字的时候, 说过, 当使用inline的方式写dom元素的事件处理函数的时候, 采用的是引用的方式. 刚好nullbyte童鞋给我提供了一个很有意思的Case:

<img id="foo" src="xxx" onerror=" alert('error');
    } function foobar() {
          alert('www.laruence.com'); " />
<script>
alert(document.getElementById("foo").onerror);
</script>

在IE下试试看..

不过, FF和Chrome下都不行, 应该是FF和Chrome都会验证html代码的合法性.

Javascript正则的效率

如果你看到有人写Javascript的trim的时候采用了循环的方式,而不是正则的方式, 请不要笑. 人家这可是经验所致, 考虑如下代码的执行时间会是多少?

var matchs = /^(a+)+$/.exec("aaaaaaaaaaaaaaaaaaaaaaaaaaaX");
alert(matchs);

告诉你吧…. 注:以下结果来自看手表估测, 但不影响时间的长度性…另外jsmore的stauren同学也验证了这一结论:

IE8: 30秒
FF3: 28秒
号称目前最快的采用V8引擎的Chrome: 8秒.

这个结果,,,是多么的不可接受啊? 具体原因的分析, 在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匹配过程中,特别是在编写不合理的正则式匹配过程中,文本被反复扫描,效率损失是不小的。明白这个道理,对于写出高效的正则表达式很有帮助。

而对于Javascript中的正则来说, 应该是优先匹配量词, 导致了很深的递归, 形成了性能问题…

Related Posts:

Tags: , , ,

Reader's Comments

  1. |

    没看明白要匹配什么?应该也是尽可能多的匹配a,但是因为最后一个是X,所以打印出null,厄,直接写a+不就行了,在PHP里很快,呵呵。

  2. |

    呵呵 好的正则 才能让正则有好的性能

  3. |

    测试了一下,果然很慢。。以后少用正则,
    可是为什么测试的正则要有两个+号呢
    /^(a+)$/.exec(“aaaaaaaaaaaaaaaaaaaaaaaaaaaX”);

    一个加号倒是很快。。

  4. |

    @cjj 有理, 正则也是一门独立的艺术.

  5. |

    首先,恭喜
    然后,国庆快乐
    最后,虽然把精通正则表达式看过了,但是对此的了解依然不够。学习了

  6. |

    求求大侠能不能帮我看个js问题啊,问题如下

    有两个页面a, b 其中a为表单页面b为数据接收页面

    a中的数据表单使用onsubmit事件验证客户端数据有效性, 但如果我在服务器(页面b)上检测到提交上来的数据不符合要求, 我使用history.go(-1), 返回前一个页面后, 在页面a数据表单无法提交(没有报任何js错误), 在表单内回车和点“submit”均无法提交表单, 经检查发现在b页面history.go(-1)回到a页面后, onsubmit事件无法响应, 此问题仅在firefox下出现, 并且firebug和错误控制台均未报出任何js错误,第一次提交的时候所有js都正常运行了的

  7. |

    b页面history.go(-1)后, a页面onsubmit事件里的任何东西都无法执行, 排除了验证函数错误

  8. |

    @toms sorry, 我没有重现出来, 你能把你的代码mail到我的yahoo邮箱么?

  9. |

    够诡异,够专业。

  10. |

    你的JS也是如此的牛啊

Leave a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word