【问题标题】:Pass a JS Object as the scope to a JS Template Literal?将 JS 对象作为范围传递给 JS 模板文字?
【发布时间】:2018-03-08 02:48:23
【问题描述】:

在python中,你可以像这样进行变量字符串插值:

song_context = { "adjective": "funny" }
ella_sings = "my {adjective} valentine".format(**song_context)

这里,song_context 对象格式化 ella_sings 字符串中的变量。

在 ES6 中是否有一种内置方法可以使用模板文字进行类似的操作?我正在寻找一种为给定字符串显式定义替换空间的快速方法。例如:

const song_context = { adjective: "funny" }
const ella_sings = `my ${adjective} valentine`.format(song_context)

上下文:我知道其他方法可以做到这一点,例如使用a template librarymultiple find and replace,但我想知道ES6 的任何部分是否支持这个用例。我浏览了template literal part of the ECMAScript 6.0 standard,它非常清楚地说明了"Let ctx be the running execution context",但似乎很难相信他们不会在必要时提供一种明确上下文的方法。

【问题讨论】:

  • 为什么要将形容词放在对象中以与字符串文字一起使用?
  • 模板文字不能替代实际的模板引擎。
  • @RobertMennell 这就是问题所在 - 我想将对象传递给模板文字,而不是使用模板文字的上下文。
  • @FelixKing 我不确定您为什么认为我试图通过使用模板文字来替换实际的模板引擎。我不想这样做。相反,我想控制模板文字的范围。
  • @P.MyerNore 那么我的答案应该正是您想要的。在基本模板文字格式中你不能,但在标记模板中你可以。

标签: ecmascript-6 template-literals


【解决方案1】:

在 ES6 中是否有一种内置的方法可以用模板文字做类似的事情?

模板文字没有特殊的逻辑。 ${..} 括号之间的代码只是一个普通的表达式,它被评估为一个值。

`my ${adjective} valentine`

总是会在本地范围内查找名为adjective 的变量。你当然可以改变它来做

`my ${song_context.adjective} valentine`

如果你不想改变那部分,那么你总是可以使用解构,例如

const {adjective} = song_context;
const ella_sings = `my ${adjective} valentine`

或使用 IIFE:

const ella_sings = ({adjective}) => `my ${adjective} valentine`)(song_context);

如果您愿意,您也可以围绕模板文字构建自己的模板系统,但它开始变得很快变得复杂,并且失去了让您首先想要使用模板文字的大部分好处。

【讨论】:

    【解决方案2】:

    您可能想在 Javascript MDN 上阅读更多关于它们的内容,并注意名为 Tagged template literals 的部分,因为它展示了如何将模板文字转换为完整的在模板上。

    出于存档目的,我将导入相关部分:

    标记的模板字面量

    模板文字的更高级形式是标记模板文字。标签允许您使用函数解析模板文字。标记函数的第一个参数包含一个字符串值数组。其余参数与表达式有关。最后,您的函数可以返回您操作的字符串(或者它可以返回完全不同的东西,如下一个示例中所述)。用于标记的函数名称可以任意命名。

    var person = 'Mike';
    var age = 28;
    
    function myTag(strings, personExp, ageExp) {
    
      var str0 = strings[0]; // "that "
      var str1 = strings[1]; // " is a "
    
      // There is technically a string after
      // the final expression (in our example),
      // but it is empty (""), so disregard.
      // var str2 = strings[2];
    
      var ageStr;
      if (ageExp > 99){
        ageStr = 'centenarian';
      } else {
        ageStr = 'youngster';
      }
    
      return str0 + personExp + str1 + ageStr;
    
    }
    
    var output = myTag`that ${ person } is a ${ age }`;
    
    console.log(output);
    // that Mike is a youngster
    

    标签函数不需要返回字符串,如下例所示。

    function template(strings, ...keys) {
      return (function(...values) {
        var dict = values[values.length - 1] || {};
        var result = [strings[0]];
        keys.forEach(function(key, i) {
          var value = Number.isInteger(key) ? values[key] : dict[key];
          result.push(value, strings[i + 1]);
        });
        return result.join('');
      });
    }
    
    var t1Closure = template`${0}${1}${0}!`;
    t1Closure('Y', 'A');  // "YAY!"
    var t2Closure = template`${0} ${'foo'}!`;
    t2Closure('Hello', {foo: 'World'});  // "Hello World!"
    

    这些标记的模板文字似乎正是您想要的。

    【讨论】:

      【解决方案3】:

      您可以创建一个编译模板然后接受上下文作为其参数的函数。唯一的问题是您需要在大括号内的占位符周围加上引号。

      const compileTemplate = (template, ...replacements) => 
          ctx => 
              template.reduce(
                  (accumulator, part, i) => 
                      accumulator + ctx[replacements[i - 1]] + part
      
                  );
      
      
      const templateFn = compileTemplate`This is a ${'adj'} problem.`;
      
      console.log(templateFn( {adj: 'hard'} ));
      console.log(templateFn( {adj: 'funny'} ));
      

      【讨论】:

        猜你喜欢
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-22
        • 2013-11-30
        • 2015-10-06
        相关资源
        最近更新 更多