是否可以创建一个模板字符串作为一个普通的字符串,

let a = "b:${b}";

然后把它转换成一个模板字符串,

let b = 10;
console.log(a.template()); // b:10

没有eval, new Function和其他动态代码生成的手段?


当前回答

我制定了自己的解决方案,用描述作为函数来处理类型

export class Foo {
...
description?: Object;
...
}

let myFoo:Foo = {
...
  description: (a,b) => `Welcome ${a}, glad to see you like the ${b} section`.
...
}

这样做:

let myDescription = myFoo.description('Bar', 'bar');

其他回答

由于模板字符串必须动态地(在运行时)获得对b变量的引用,所以答案是:不,没有动态代码生成是不可能做到的。

但是,使用eval非常简单:

let tpl = eval('`'+a+'`');

我提出了这个实现,它的工作就像一个魅力。

function interpolateTemplate(template: string, args: any): string {
  return Object.entries(args).reduce(
    (result, [arg, val]) => result.replace(`$\{${arg}}`, `${val}`),
    template,
  )
}

const template = 'This is an example: ${name}, ${age} ${email}'

console.log(interpolateTemplate(template,{name:'Med', age:'20', email:'example@abc.com'}))

如果在模板中没有找到arg,可能会引发错误

您可以参考这个解决方案 Const interpolate = (str) => new Function(' return \ ' ${new String(str)}\ '; ')(); const foo = 'My'; Const obj = { 文本:汉尼拔·莱克特 firstNum: 1、 secondNum: 2 } Const STR = "${foo}名称为:${obj.text}。Sum = ${obj。firstNum} + ${obj。secondNum} = ${obj。firstNum + obj.secondNum}"; console.log(插入(str));

因为我们正在重新发明一些东西,这将是javascript中的一个可爱的特性。

我使用eval(),这是不安全的,但javascript是不安全的。我承认我不擅长javascript,但我有一个需求,我需要一个答案,所以我做了一个。

我选择用@而不是$来风格化我的变量,特别是因为我想使用文字的多行特性,直到它准备好才计算。变量语法是@{optionalobject。optionalobjectn。variable_name}

我不是javascript专家,所以我很乐意听取改进建议,但是……

var prsLiteral, prsRegex = /\@\{(.*?)(?!\@\{)\}/g
for(i = 0; i < myResultSet.length; i++) {
    prsLiteral = rt.replace(prsRegex,function (match,varname) {
        return eval(varname + "[" + i + "]");
        // you could instead use return eval(varname) if you're not looping.
    })
    console.log(prsLiteral);
}

下面是一个非常简单的实现

myResultSet = {totalrecords: 2, 姓名:["Bob", "Stephanie"], 37岁的年龄:[22]}; rt = '我的名字是@{myResultSet。我是@{myResultSet.Age}。' var prsLiteral, prsRegex = /\@\{(.*?)(?!\@\{)\}/g . var prsLiteral, prsRegex = /\@\ For (i = 0;i < myResultSet.totalrecords;我+ +){ prsLiteral = rt.replace(prsRegex,函数(匹配,varname) { 返回eval(varname + "[" + I + "]"); //如果不循环,可以使用return eval(varname)。 }) console.log (prsLiteral); }

在我的实际实现中,我选择使用@{{variable}}。再来一组大括号。不太可能意外地遇到这种情况。的正则表达式 /\@\{\{(.*?)(?!\@\{\{)\}\}/ g

为了便于阅读

\@\{\{    # opening sequence, @{{ literally.
(.*?)     # capturing the variable name
          # ^ captures only until it reaches the closing sequence
(?!       # negative lookahead, making sure the following
          # ^ pattern is not found ahead of the current character
  \@\{\{  # same as opening sequence, if you change that, change this
)
\}\}      # closing sequence.

如果您对正则表达式没有经验,一个非常安全的规则是转义每个非字母数字字符,并且不要不必要地转义字母,因为许多转义字母对于几乎所有类型的正则表达式都具有特殊意义。

这个解决方案不需要ES6:

function render(template, opts) {
  return new Function(
    'return new Function (' + Object.keys(opts).reduce((args, arg) => args += '\'' + arg + '\',', '') + '\'return `' + template.replace(/(^|[^\\])'/g, '$1\\\'') + '`;\'' +
    ').apply(null, ' + JSON.stringify(Object.keys(opts).reduce((vals, key) => vals.push(opts[key]) && vals, [])) + ');'
  )();
}

render("hello ${ name }", {name:'mo'}); // "hello mo"

注意:Function构造函数总是在全局作用域中创建,这可能会导致全局变量被模板覆盖,例如render("hello ${someGlobalVar = 'some new value'}", {name:'mo'});