Javascript 函数组合的意外行为

Javascript 函数组合的意外行为,javascript,lodash,Javascript,Lodash,我正在编写一个小的实用函数,用于将字符串从一个分词方案转换为另一个分词方案。整个项目都在使用它,我知道它附带了.camelCase之类的东西,但我觉得不使用那些方案转换帮助程序更具可扩展性 其想法是,其他开发人员可以轻松地将自己的方案定义添加到我已有的方案定义中: const CASES = [ {name: 'lower_kebab', pattern: /^[a-z]+(_[a-z]+)*$/g, to_arr: w=> w.split('_'), to_

我正在编写一个小的实用函数,用于将字符串从一个分词方案转换为另一个分词方案。整个项目都在使用它,我知道它附带了
.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('')},

    //...
];
因此,每个
大小写
都需要一个模式来确定字符串是否属于该模式,一个
to_arr
来适当地分割字符串,一个
to_str
来将一个单词数组连接到该模式的字符串中(
名称
是可选的,但最好是描述性的)。我把这两个都包括在内,因为它是从
lower_kebab
UpperCamel
的转换过程中,我得到了一些意想不到的行为

我实现了如下实际转换函数:


$(文档).ready(()=>{
风险值案例=[
{名称:'下烤肉串',图案:/^[a-z]+([a-z]+)*$/g,
to_arr:w=>w.split(''uu'),
to_str:a=>a.map(w=>w.toLowerCase()).join(“”)
},
{name:'UpperCamel',模式:/^([A-Z][A-Z]*)+$/g,
to_arr:w=>w.match(/[A-Z][A-Z]*/g),
to_str:a=>a.map(u.capitalize).join(“”)
},
//...
];
函数转换为(目标方案示例){
返回uu.compose(
CASES.find(c=>c.pattern.test(target\u scheme\u example)).to\u str
,str=>CASES.find(c=>c.pattern.test(str)).to_arr(str));
}
$('go')。在('click',()=>$('result')。文本(
将_转换为($('#dst').val())($('#src').val())
));
});
尝试“上骆驼肉”到“下烤肉串”,反之亦然

转换 结果:

来自:

在同一全局正则表达式实例上多次调用的
test()
将超过上一个匹配项

这就是为什么它只在第一次工作的原因:正则表达式对象(
模式
)保持先前对其执行
测试
方法所产生的状态

要避免这种行为,可以执行以下操作之一:

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

  • 改为使用该方法,交换字符串和正则表达式的位置:

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

    在同一全局正则表达式实例上多次调用的
    test()
    将超过上一个匹配项

    这就是为什么它只在第一次工作的原因:正则表达式对象(
    模式
    )保持先前对其执行
    测试
    方法所产生的状态

    要避免这种行为,可以执行以下操作之一:

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

  • 改为使用该方法,交换字符串和正则表达式的位置:

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

  • CASES.find(c=>c.pattern.test(target\u scheme\u example)).to\u str
    不保留任何关于Javascript中对象的
    to\u str
    方法的信息。但是,你的
    似乎并不需要这些信息。我假设
    编写
    (或者更确切地说,编写
    的结果)会这样做,也就是说,为了运行
    f(g(x))
    我需要保留
    f
    g
    。有没有一个好的方法可以达到这个效果?你是否希望
    .compose(f,g)
    g
    之前应用
    f
    ?这看起来像是你所期待的。我可以看到它看起来像什么,但我想我有正确的构图顺序。要应用的第一个函数(
    compose
    的最后一个参数)应该是
    f:String->Array
    ,它是
    到arr
    的签名。第一个参数的情况类似,但是使用
    to_str
    时,您正在字符串->数组部分中使用
    c=>c.pattern.test(str)
    ,这将要求
    str
    已经匹配模式。也许你把
    str
    target\u scheme\u示例
    搞混了。
    CASES.find(c=>c.pattern.test(target\u scheme\u示例))。to\u str
    不保留Javascript中对象的
    to\u str
    方法。但是,你的
    似乎并不需要这些信息。我假设
    编写
    (或者更确切地说,编写
    的结果)会这样做,也就是说,为了运行
    f(g(x))
    我需要保留
    f
    g
    。有没有一个好的方法可以达到这个效果?你是否希望
    .compose(f,g)
    g
    之前应用
    f
    ?这看起来像是你所期待的。我可以看到它看起来像什么,但我想我有正确的构图顺序。要应用的第一个函数(
    compose
    的最后一个参数)应该是
    f:String->Array
    ,它是
    到arr
    的签名。第一个参数的情况类似,但是使用
    to_str
    时,您正在字符串->数组部分中使用
    c=>c.pattern.test(str)
    ,这将要求
    str
    已经匹配模式。也许你把
    str
    target\u scheme\u示例
    搞混了。在实际应用中,我可能通过将
    CASES
    设置为
    const
    使自己产生了一种虚假的安全感。从每个案例的模式中移除全局标志就成功了!事实上,
    const
    只禁止重新分配到所讨论的变量,而不是它的突变。我可能通过在实际的ap中将
    CASES
    设置为
    const
    使自己陷入了一种错误的安全感