功能组合的意外行为

时间:2016-12-29 23:20:20

标签: javascript lodash

我正在编写一个小实用程序函数来将字符串从一个单词分隔方案转换为另一个。整个项目正在使用lodash,我知道这些内容有_.camelCase之类的内容,但我觉得不利用这些方案转换助手更具可扩展性。

我们的想法是,其他开发人员可以轻松地将自己的方案定义添加到我已有的方案中:

const CASES = [

    {name: 'lower_kebab', pattern: /^[a-z]+(_[a-z]+)*$/g,
     to_arr: w=> w.split('_'),
     to_str: a=> a.map(w=>w.toLowerCase()).join('_')},

    {name: 'UpperCamel', pattern: /^([A-Z][a-z]*)+$/g,
     to_arr: w=> w.match(/[A-Z][a-z]*/g),
     to_str: a=> a.map(_.capitalize).join('')},

    //...
];

因此每个Case需要一个模式来确定一个字符串是否属于该方案,一个to_arr来分配该字符串,一个to_str将一个单词数组加入一个该方案的字符串(name是可选的,但描述性很好)。我已经将这两个包括在从lower_kebabUpperCamel的转换中,我在这里遇到了一些意想不到的行为。

我已经实现了这样的实际转换功能:



<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.3/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.3/lodash.fp.min.js"></script>

<script>
$(document).ready(()=>{

  var CASES = [
    
    { name: 'lower_kebab', pattern: /^[a-z]+(_[a-z]+)*$/g,
      to_arr: w=> w.split('_'),
      to_str: a=> a.map(w=>w.toLowerCase()).join('_')
    },
     
    { name: 'UpperCamel', pattern: /^([A-Z][a-z]*)+$/g,
      to_arr: w=> w.match(/[A-Z][a-z]*/g),
      to_str: a=> a.map(_.capitalize).join('')
    },
    
    //...
    
  ];
  
  function convert_to(target_scheme_example){
    return _.compose(
            CASES.find(c=>c.pattern.test(target_scheme_example)).to_str
    , str=> CASES.find(c=>c.pattern.test(str)).to_arr(str) );
  }
  
  $('#go').on('click', ()=> $('#result').text(
      convert_to( $('#dst').val() )( $('#src').val() )
  ));
  
});
 
</script>

<p>Try "<strong>UpperCamel</strong>" to "<strong>lower_kebab</strong>" and vice-versa.</p>
<input id="dst" value="UpperCamel" placeholder="Example of target scheme">
<input id="src" value="lower_kebab" placeholder="String to convert">

<button id="go">Convert</button>

<div>
  <p><strong>Result:</strong></p>
  <p id="result"></p>
</div>
&#13;
&#13;
&#13;

&#34;真实&#34;版本严格地存在于服务器端代码中,因此片段中所有与DOM相关的内容纯粹用于演示目的(&#34;真正的&#34;版本也使用我排除的_.get进行一些错误检查这里为了简洁)。

这里的事情变得奇怪。

在服务器端,问题显示为convert_to('UpCa')('activity_template')评估"Activity_template""activity template"等内容。在演示片段中,我认为同样的问题表现为只能点击&#34;转换&#34;只有一次没有抛出异常。

有什么想法?我的RegEx有点关吗?我误解了如何使用_.compose吗?如果这个工具刚好被打破了,那就是一件事,但它确实让我失去了它在很多情况下的工作方式,但不是全部。

1 个答案:

答案 0 :(得分:2)

来自documentation on RegExp#test

  在同一个全局正则表达式实例上多次调用的

test()将超过上一个匹配。

这就是它第一次只能工作的原因:正则表达式对象(pattern)维护上次执行test方法所产生的状态。

要避免此行为,您可以执行以下操作之一:

  1. g正则表达式中删除pattern修饰符,因为它们对于您尝试进行的匹配类型不是必需的,或者

  2. 使用String#match方法,交换字符串的位置和正则表达式:

    return _.compose(
        CASES.find(c=>target_scheme_example.match(c.pattern)).to_str
                 , str=> CASES.find(c=>str.match(c.pattern)).to_arr(str) );
    }