【问题标题】:Setting context for ES6 template literal within a Function constructor?在 Function 构造函数中为 ES6 模板文字设置上下文?
【发布时间】:2018-08-08 14:35:20
【问题描述】:

我的应用获取资源字符串 + 占位符标记的列表,它应该使用给定值更改标记。

此类资源的一个示例是:"http://example.com/?name=${name}&age=${age}";

(我在一个数组中有很多这样的东西,但这不相关)。

所以现在我有了这个^ 字符串并且我有了值。所以我需要生成消化后的字符串。

当然我可以使用eval

var template = "http://example.com/?name=${name}&age=${age}";
var name = "John";
var age = "30";
var url = eval(`\`${template}\``);
console.log(url); //http://example.com/?name=John&age=30

这可行。但我不想使用eval

所以我改用new Function()() 的其他方法:

var url = new Function ('tmpl','obj','return `${tmpl}`')

这产生了函数:

ƒ anonymous(tmpl,obj ) {
return `${tmpl}`
}

所以现在我可以做:

new Function ('tmpl','obj','return `${tmpl}`')(template ,{name, age})

但现在我需要在内部函数中拆分 obj 以便模板字面量知道值

顺便说一句 - 我试过了 - 没有成功:

(new Function ('tmpl','obj','return `${tmpl}`').bind({name,age})) (template)

问题

如何在内部函数中展平obj,以便${} 具有已知的本地值?

铌 我不喜欢使用正则表达式解决方案,因为模板文字中有换行符。此外,这些资源故意采用 es6 模板字符串的格式

Online-demo

【问题讨论】:

  • 您仍然需要 eval 将字符串转换为模板。使用函数不会改变这一点。
  • @KevinB 函数返回一个模板 "return ${tmpl}"
  • 是的,但这不会满足您的要求。
  • 您的功能甚至不起作用。它只是将tmpl 作为字符串返回。
  • 您正在将模板文字用于它不打算用于的东西。这就是我们在 ES6 中仍然使用模板引擎的原因。

标签: javascript ecmascript-6 template-literals


【解决方案1】:

我已经设法用我想要的模板字符串解决了这个问题。

setString(resource: string, obj: {}) {
    const names = Object.keys(obj);
    const vals = Object.keys(obj).map(key => obj[key]);
    return new Function(...names, `return \`${resource}\`;`)(...vals);
  }

var str = "We've sent your code to ${phone}.";
console.log(this.setString(str, { phone: 123 }))

输出:

“我们已将您的代码发送到 123。”

Demo

【讨论】:

  • 所以您不想使用eval,但可以使用new Function?我希望你意识到它们本质上是做同样的事情......:在运行时将动态字符串解析为代码。
  • 新函数不像 eval。 Eval 可以访问我的本地方法的本地变量。当然我可以将 eval 移动到一个单独的方法,但除此之外 eval 创建一个新的执行上下文,而函数不是
  • 两者都在运行时将字符串解析为代码,这是eval 的主要关注点:同样的关注点也适用于new Function。这就是我的观点。
【解决方案2】:

您的eval 解决方案的正确new Function 替代品是

var template = "http://example.com/?name=${name}&age=${age}";
var makeUrl = new Function("{name, age}", "return `" + template + "`;");
var url = makeUrl({name: "John", age: 30});
console.log(url); //http://example.com/?name=John&age=30

您的函数刚刚返回传递给它的 tmpl 字符串。

【讨论】:

  • Bergi - 这意味着每次参数部分我都必须写入:new Function("{name, age}"。 (不同的资源可能有不同的令牌)......无论如何让它动态?
  • 是的,您需要在某个时候决定哪些变量可用。你可以做new Function("obj", "with (obj) { return "+template+"; }"),但显然不推荐。您可以从任何可用的来源构建解构表达式。
猜你喜欢
  • 2013-09-01
  • 1970-01-01
  • 2019-07-04
  • 2017-10-31
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
相关资源
最近更新 更多