扩展@Bergi的回答,当你意识到你不仅可以返回纯字符串,还可以返回任何结果时,标记模板字符串的威力就显现出来了。在他的示例中,标签构造并返回一个带有闭包和函数属性format
的对象。
在我最喜欢的方法中,我仅返回一个函数值,您可以稍后调用它并传递新参数以填充模板。像这样:
function fmt([fisrt, ...rest], ...tags) {
return values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
}
或者,对于代码高手来说:
let fmt=([f,...r],...t)=>v=>r.reduce((a,c,i)=>a+v[t[i]]+c,f)
然后,您需要构建模板并延迟替换:
> fmt`Test with ${0}, ${1}, ${2} and ${0} again`(['A', 'B', 'C']);
// 'Test with A, B, C and A again'
> template = fmt`Test with ${'foo'}, ${'bar'}, ${'baz'} and ${'foo'} again`
> template({ foo:'FOO', bar:'BAR' })
// 'Test with FOO, BAR, undefined and FOO again'
另一个选择,更接近于您所写的内容,是返回一个继承自字符串的对象,以获得开箱即用的鸭子类型并遵守接口。扩展
String.prototype
将无法工作,因为您需要模板标签的闭包来稍后解析参数。
class FormatString extends String {
}
function fmt([fisrt, ...rest], ...tags) {
const str = new FormatString(rest.reduce((acc, curr, i) => `${acc}\${${tags[i]}}${curr}`, fisrt));
str.format = values => rest.reduce((acc, curr, i) => {
return acc + values[tags[i]] + curr;
}, fisrt);
return str;
}
接着,在调用现场:
> console.log(fmt`Hello, ${0}. This is a ${1}.`.format(["world", "test"]));
> template = fmt`Hello, ${'foo'}. This is a ${'bar'}.`
> console.log(template)
> console.log(template.format({ foo: true, bar: null }))
您可以在
这个答案中查看更多信息和应用。
.format()
方法,你不应该使用模板字符串,而是应该使用普通的字符串字面量。 - Bergi\
foo ${5+6}`会被计算为
"foo 11"`将格式方法附加到字符串原型上,可以让您做一些愚蠢的事情,比如:`\`My ${5+6}th token is {0}\`.format(11)`
这应该被计算为"My 11th token is 11"
。 - Hovis Biddle