变量的字符串插值

31

假设我有一个变量str

var str = "123"

现在我可以执行console.log(`Hello ${str}`),它会输出Hello 123

现在我有另一个变量strnew

var strnew = 'Hello ${str}'
基于回答/评论 - strnew 是从文件中读取的,所以它始终是一个字符串,不能用 ` 替换。
如何使用 console.log(...) 打印 Hello 123?
是否可能在没有任何 eval() 的情况下实现?

2
可能相关:https://dev59.com/N5vga4cB1Zd3GeqP9OyO - deceze
1
我认为在这种情况下最好的方法是使用一个接受 str 的函数,并在内部使用此模板字符串。 - Dmitry Masley
如果字符串来自文件,最好使用_.template或其他模板引擎。我没有看到任何选项可以从字符串生成模板字符串。 - Dmitry Masley
如果您不使用作用域,请使用正则表达式替换,如strnew.replace(/\$\{(.*?)\}/g,()=>window[RegExp.$1])。请将以下与程序相关的内容翻译为中文。仅返回翻译后的文本: - Josh Lin
使用字符串模板与简单字符串的原因是什么? - The Reason
显示剩余3条评论
4个回答

35

通过像 ${str} 这样简单的方式,您可以使用简单的字符串替换:

var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]);

var tpl = 'Hello ${str} and ${other}';

console.log(template(tpl, {str: 'foo', other: 'bar'}));

通常情况下,不行,除非使用eval(除非编写自己的JavaScript解释器),因为${...}可以包含任意表达式。

为了完整起见,这里是使用eval的解决方案:

var template = function(tpl, args) {
    var keys = Object.keys(args),
        fn = new Function(...keys, 
          'return `' + tpl.replace(/`/g, '\\`') + '`');
    return fn(...keys.map(x => args[x]));
};


function test() {
    var myTpl = 'Hello ${str + "!"} and ${other.toUpperCase()}';
    console.log(template(myTpl, {str: 'foo', other: 'bar'}));
}

test();


非常抱歉,我编辑了您的帖子而不是建议进行编辑,但我已经恢复了它。new Function('', 'return ' + tpl + ''); 可以优化为 new Function('return ' + tpl + '');。 - Lyubomir
非常好的答案!!这应该是被采纳的答案。请给我一两天时间确认。 - Faiz Mohamed Haneef
1
这段代码隐式地创建了两个全局变量。传递给函数的参数从未被使用过。template(myTpl, str='foo', other='bar') - Qwertiy
1
@Qwertiy:没错,最近用了太多Python ;) 已经修复了。 - georg

1
你可以使用函数而不仅是字符串。

var strnew = function(str){
  return `Hello ${str}`;
}
var str = "123";
console.log(strnew(str))


2
在我看来,最好的解决方案并且很可能是模板字面量被设计使用的方式。 - nils
模板字符串是从文件中读取的,它们不在 OP 的代码中。 - georg
@georg 是的,他后来添加了这个注释,我写了关于此的评论。 - Dmitry Masley
是的。根据答案,我不得不调整我的问题。谢谢@dm。 - Faiz Mohamed Haneef

0

感谢这个答案,以下是一些黑魔法代码,可以实现您想要的功能。免责声明 - 这只是为了好玩/非常有限和奇特的应用程序。它很可能非常缓慢,并且在许多边缘情况下会崩溃,但在您问题的有限范围内,它可以工作。

function getString(){
 return "calculating ${foo} + ${bar} = ${foo + bar}";
}

var localEnvironmentProxy = new Proxy({}, {
    has(target, prop) { return true; },
    get(target, prop) { return (prop in target ? target : window)[prop]; }
  });
  
  with(localEnvironmentProxy){
  
 var foo = 1;
 var bar = 2;
  
 var templString = getString();
 
 var fnFullText = 'with(arguments[0]){ return `' + templString + '`;}';
 
 var tempalteFn = new Function(fnFullText);
    
 console.log(tempalteFn(localEnvironmentProxy));
    //calculating 1 + 2 = 3
  
  }


0

我基于@georg上面的答案构建了一个TypeScript解决方案:

public renderTemplate(templateStr: string, args: any): string {
  templateStr = templateStr.replace(/`/g, '\\`');
  
  const keys = Object.keys(args);

  const fn = new Function(...keys, 'return `' + templateStr + '`');

  return fn(...keys.map(key => args[key]));
}

使用方法基本相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接