【问题标题】:Get wildcarnames from string template从字符串模板获取通配符
【发布时间】:2017-04-29 23:53:34
【问题描述】:

有没有一种快速的方法(我的意思是一种已知的方法)从字符串模板中获取通配符名称?,比如...

const str = `Hello ${name}, today is ${weekday}!`;
getWildCards(str); // will return ['name', 'weekday']

我正在创建一个翻译工具,translation 函数不会提前知道通配符。

【问题讨论】:

    标签: javascript string templates wildcard


    【解决方案1】:

    编辑:

    实际上,有一种使用 tagged template literals 从模板文字中提取参数的本地方法,它允许您使用以下形式的函数解析模板文字:

    function tag(strings, param1, param2, ..., paramN) { ... }
    

    因此,如果您在模板文字 (${ foo }) 的表达式中不使用变量,而是使用字符串 (${ 'foo' }),那么如果您这样做:

    tag`${ 'a' }${ 'b' } - XXX ${ 'c' }`
    

    strings 将是 ['', '', ' - XXX ', ''],您将收到 3 个参数,其值为 'a''b''c'

    你可以从标签函数返回你想要的任何东西,所以对于你的用例来说,一个好的解决方案是返回一对[paramsList, closure],其中闭包将是一个接收对象(映射)的函数,参数为在原始字符串文字中使用并使用它们来构建结果字符串。像这样:

    function extractParams(strings, ...args) {
      return [args, dict => {   
        return strings[0] + args
          .map((arg, i) => dict[arg] + strings[i + 1]).join('');
      }];
    }
    
    const [params, translate] = extractParams`Hello ${ 'name' }, today is ${ 'weekday' }`;
    
    console.log(params);
    console.log(translate({ name: 'Foo', weekday: 'Barday' }));

    原始答案:

    假设模板字符串被包装到一个函数中,这样它就不会抛出ReferenceError,并且您稍微更改了模板字符串的格式,以便使用的参数始终是对象的属性,您可以为此使用proxy

    假设你有这样的东西:

    function getSentence(key, args = {}) {
      // Note that for the proxy solution to work well, you need to wrap each of them
      // individually. Otherwise you will get a list of all the params from all the
      // sentences.
    
      const sentences = {
          salutation: (args) => `Hello ${ args.name }, today is ${ args.weekday }!`,
          weather: (args) => `Today is ${ args.weather } outside.`,
      };
    
      return sentences[key](args) || '';
    }
    
    function extractParams(key) {
      const params = [];
      
      const proxy = new Proxy({}, {
        get: (target, name) => {
          params.push(name);
        },
      });
      
      getSentence(key, proxy);
      
      return params;
    }
    
    console.log(extractParams('salutation'));

    无论如何,请注意,这仅在您的参数中只有一个级别深度时才有效,否则您将需要一个返回另一个代理的代理,该代理返回另一个代理......并跟踪路径(prop.subprop...)。他们还应该返回一个function,它返回一个string,作为最后一个将被插入到结果字符串中的属性。

    function getSentence(key, args = {}) {
      // Note that for the proxy solution to work well, you need to wrap each of them
      // individually. Otherwise you will get a list of all the params from all the
      // sentences.
    
      const sentences = {
          salutation: (args) => `Hello ${ args.name }, today is ${ args.a.b.c.d }!`,
          weather: (args) => `Today is ${ args.weather } outside.`,
      };
    
      return sentences[key](args) || '';
    }
    
    function getProxy(params, path = []) {
      return new Proxy({}, {
        get: (target, name) => {
          if (typeof name === 'symbol') {
            params.push(path);
            
            return () => ''; // toString();
          } else {
            return getProxy(params, path.concat(name));
          }
        },
      });
    }
    
    function extractParams(key) {
      const params = [];
      
      getSentence(key, getProxy(params));
      
      return params;
    }
    
    console.log(extractParams('salutation'));

    【讨论】:

    • @r01010010 检查我的更新,这可能是一个更好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多