Javascript exec维护状态

时间:2016-11-28 08:10:08

标签: javascript regex

我目前正在尝试在Javascript中构建一个小模板引擎,方法是将html5标签中的标签替换为find并替换为正则表达式。

我在正则表达式上使用exec而且我正在循环结果。我想知道为什么正则表达式在当前形式中以正则表达式上的/ g标志中断,但没有它会好吗?

检查损坏的示例并删除正则表达式上的/ g标志以查看正确的输出。

var TemplateEngine = function(tpl, data) {
  var re = /(?:&lt;|<)%(.*?)(?:%&gt;|>)/g, match;
  while(match = re.exec(tpl)) {  
    tpl = tpl.replace(match[0], data[match[1]])
  }

  return tpl;
}

https://jsfiddle.net/stephanv/u5d9en7n/

有人可以向我详细解释为什么我的例子完全打破了:

<p><%more%></p>

2 个答案:

答案 0 :(得分:1)

点击此链接https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex。使用g标志时,存储正则表达式的对象(重新)将跟踪lastIndex属性中最后一个匹配的位置,下次使用该对象时,搜索将从lastIndex

要解决此问题,您可以每次手动重置lastIndex属性,也可以不将正则表达式保存在对象中并像内联使用它一样:

while(match = /(?:&lt;|<)%(.*?)(?:%&gt;|>)/g.exec(tpl)) {

答案 1 :(得分:1)

原因在javascript string exec strange behavior中解释。

您需要的解决方案实际上是String.replace,其中有一个回调代替:

var TemplateEngine = function(tpl, data) {
  var re = /(?:&lt;|<)%(.*?)(?:%&gt;|>)/g, match;
  return tpl.replace(re, function($0, $1) { 
     return data[$1] ? data[$1] : $0;
  });
}

请参阅updated fiddle

这里,正则表达式按顺序查找字符串中的所有非重叠匹配,并将匹配传递给回调方法。 $0是完整匹配,$1是第1组内容。如果data[$1]存在,则用于替换整个匹配,否则,将插回整个匹配。