变量的字符串插值

IT技术 javascript ecmascript-6
2021-03-04 02:51:34

说我有一个变量 str

var str = "123"

现在我可以做console.log(`Hello ${str}`),它会打印Hello 123

现在我有另一个变量 strnew

var strnew = 'Hello ${str}'

注意(基于答案/评论) -strnew从文件中读取,因此它始终是一个字符串并且不能替换为`

我如何console.log(...)打印Hello 123

有没有可能没有任何种类 eval()

4个回答

${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(缺少编写自己的 js 解释器),因为${...}可以包含任意表达式。

为了完整起见,这里是 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();

template(myTpl, str='foo', other='bar')这段代码隐式地创建了两个全局变量。从不使用传递给函数的参数。
2021-04-24 02:51:34
非常抱歉,我编辑了您的帖子而不是建议进行编辑,但我已将其还原。new Function('', '返回' + tpl + ''); 可以优化为 new Function('return ' + tpl + '');
2021-04-28 02:51:34
很好的答案!!这应该是公认的答案。给我一两天时间来确认。
2021-05-07 02:51:34
@Qwertiy:对了,最近 Python 太多了 ;) 已修复。
2021-05-13 02:51:34

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

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

@georg 是的,他后来添加了这个注释,我写了关于这个的评论。
2021-04-22 02:51:34
是的。根据答案,我不得不调整我的问题。谢谢@dm
2021-05-03 02:51:34
模板字符串是从文件中读取的,它们不在 OP 的代码中。
2021-05-08 02:51:34
恕我直言,最好的解决方案,可能也是模板文字的使用方式。
2021-05-15 02:51:34

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

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
  
  }

我根据上面@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]));
}

用法也几乎相同。