Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

正则的 exec 方法适合用 Generator 封装

  Generator 就是用来创建 Iterator 的,而 Iterator 的最大用途就是用于不定长序列的迭代遍历。在 JavaScript 中,最容易让我想到的不定长序列就是正则匹配时的 exec 了。所以我觉得正则表达式的 exec 方法非常适合用 Generator 来封装,然而目前的规范并没有这么干。
  用正则在一个字符串上匹配可能是一个很耗时的工作,目标字符串可能很大,不知道要回朔多少次才可以匹配到下一项。如果我们一股脑地把所有项都匹配出来势必是非常浪费资源的。有时候我们只要前面的几项而已,于是这时候就会使用 exec 来迭代。最简单的迭代方式可以这样 <script> var string = '12345678'; var regexp = /../g; while(regexp.exec(string)) { console.log(RegExp.lastMatch); } </script>   由于 RegExp 上有个静态属性 lastMatch 可以获取到最后一次正则匹配的结果,所以这种简单的迭代不需要中间变量。但 RegExp.lastMatch 毕竟只有一个,如果存在嵌套之类的情况就需要中间变量来储存结果了。
<script> var string = '12345678'; var regexp = /../g; for(var i; i = regexp.exec(string);) { console.log(i[0]); } </script>   但是这么一个恶心的循环实在太难受了,如果是一个标准的迭代器,也许就会好得多吧?只不过原生没有实现这样的迭代器,我们得自己封装一个。但考虑到正则对象是有状态的,我们还得写一坨克隆正则对象的代码,比如下面这个封装 var matchAllAsIterator = function * (string, regexp) { // Clone a regexp object let flags = []; if(regexp.global) flags.push('g'); if(regexp.ignoreCase) flags.push('i'); if(regexp.multiline) flags.push('m'); if(regexp.sticky) flags.push('y'); let newRegexp = new RegExp(regexp.source, flags.join('')); newRegexp.lastIndex = regexp.lastIndex; // Iterator for(let i; i = newRegexp.exec(string); yield i[0]); };   然后在使用时只需要简单地调用即可 var string = '<div><span></span></div>'; var regexp = /<.*?>/g; for(let i of matchAllAsIterator(string, regexp)) { console.log(i); };   这样业务代码的语义就通顺多了,而且即使嵌套也不成问题。
  上面的 matchAllAsIterator 生成器只是随手写的一坨代码,不建议复制到项目中使用。我只是觉得规范如果提供迭代器版的正则匹配也许会让正则更容易使用。
网名:
3.80.55.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^