使用功能构建ES6模板文字

时间:2018-10-19 10:54:57

标签: javascript regex

我有一个字符串,其中包含模板文字变量,但由于它是动态构建的,因此不是模板文字。我想不做eval()就将它转换成模板“ literal”:

   // this is dynamically created by an algo:
   const vars = '${var1} ${var2}';
   const str = 'the result is ' + vars;

   // this works, but it's nasty: 
   eval('result = `' + str + '`');

我正在寻求本着RegExp类的精神访问内部模板构建器的方法,该类可用于代替标准regexp文字斜杠//

   const myRegex = '^(\d+)$';
   new RegExp(myRegex);

这样我可以做到:

   const myStr = 'I want to be ${foo}';
   const foo = 99;
   const lit = new TemplateLiteral(myStr);
   console.log( lit.run() ); // I want to be 99

2 个答案:

答案 0 :(得分:3)

您不能“构建文字”。这是一个矛盾。文字是源代码中的一种语法,可以编译为一个值。

new RegExp(...)生成一个新的regexp对象,而不是一个regexp文字。 RegExp文字是您实际写/.../的时候。

以相同的方式,仅当您在代码中编写'...'"..."`...`时,字符串文字才是字面值。您可以构建 string -通常使用串联-但无法构建字符串 literal

编辑:快速又肮脏:

function makeTemplate(template) {
  return new Function("return `" + template + "`");
}

const myStr = 'I want to be ${foo}';
const foo = 99;
const template = makeTemplate(myStr);
console.log(template());
// I want to be 99

但是,尽管new Function总是比eval更好,但适用于执行不可信字符串的通常免责声明。

有关更安全的选择,请参见Mustache.jsPug.js(不是我在评论中说过的Pod,抱歉),作为领先的JavaScript模板库。

答案 1 :(得分:1)

这里的关键问题是您在第一个代码块中的注释内容:

  

这是由算法动态创建的

如果模板是由算法创建的,则您的选择是:

  • 不要使用内置模板功能,请使用几个类似的模板库中的任何一个(或编写自己的模板库)
  • 使用eval或其表亲之一(最好是new Function

您不能动态创建模板文字。他们是文字。 :-)

如果我们对您的算法有更多了解,我们也许可以为您提供更好的帮助。例如,您可能可以让算法创建一个函数,然后使用可能需要的信息来调用该函数:

function getVarsFormatter(var1First) {
    if (var1First) {
        return (var1, var2) => `${var1} ${var2}`;
    } else {
        return (var1, var2) => `${var2} ${var1}`;
    }
}

然后

const formatter = getVarsFormatter(flag);
const result = formatter("this is var1", "this is var2");

实时示例:

function getVarsFormatter(var1First) {
    if (var1First) {
        return (var1, var2) => `${var1} ${var2}`;
    } else {
        return (var1, var2) => `${var2} ${var1}`;
    }
}

for (let n = 0; n < 6; ++n) {
  const formatter = getVarsFormatter(Math.random() < 0.5);
  const result = formatter("this is var1", "this is var2");
  console.log(result);
}