【问题标题】:ES6 template statement versus eval()ES6 模板语句与 eval()
【发布时间】:2016-02-03 16:52:28
【问题描述】:

我正在考虑对文本字符串中的${something} 变量进行独立解析,对它们执行eval() 并在结果字符串中替换。

是否有任何特定于 ES6 模板变量需要注意的地方?是什么让它们的行为与标准 eval() 的行为方式不同?

例子:

var value = // a string, number, object,... anything;

var a = `${value}`; // use ES6 template string
var b = '${value}'.replace('${value}', eval(value));

ab 的结果在哪些方面以及为什么会有所不同?

【问题讨论】:

  • 您检查过规格吗? eval 不能替代模板字符串变量的工作方式。
  • 如果你询问 eval,以任何不同于“不要使用 eval”的方式,你都会得到反对意见。
  • @vitaly-t:如果您在问题中包含实际代码会有所帮助。您对“考虑做什么”的描述不足以给出合理的答案,我不知道您想如何以类似于模板文字行为的方式使用 eval
  • @vitaly-t:这并不像你想象的那样有效。如果您只是省略 eval 调用并将替换模式替换为 value,它会更好(更接近模板文字)
  • 好吧..您的示例在当前形式中并没有多大意义,所以...改进它将使我们可以建立它。在当前示例中,value 是一个字符串,您正在评估该字符串。它将引发异常,因为 any kind of value 不是有效的 javascript。

标签: javascript node.js


【解决方案1】:

考虑这个例子:

var a = 'test';

var str1 = `${a} ${a} ${a}`; //test test test
var str2 = '${a} ${a} ${a}'.replace('${a}', a); //test ${a} ${a}

另外,请考虑以下事项:

var str1 = `${Math.random()} ${Math.random()}` //0.7818185299239435 0.8991473634359528
var str2 = '${Math.random()} ${Math.random()}'.replace('${Math.random()}', Math.random()); //0.9327690218686401 ${Math.random()}

请记住,${...} 中的任何内容都将被评估为代码,其结果将用于字符串中。

您可以争论使用正则表达式之类的,但也可以考虑一下:

var str1 = `${5+`${Math.random()}`}`; //50.11300474012906858

是的,模板字符串可以嵌套!你会如何处理替换?


所以,在一个小列表中:

  • 将评估所有内容
  • 模板字符串可以嵌套
  • 结果将是字符串的一部分
  • 执行结果可能会有所不同

这就是区别。


您可以询问安全性。嗯,它的危险性不亚于var a = eval('str')var a = Function('return str')()

但是,有一个转折点:它将在返回值上运行.toString()。最小的可验证示例如下:

alert(`${{}}`) // calling alert`${{}}` will only show ","

如果您设法以这种假设的方式使用您的方法:

alert('${R}'.replace( /\$\{(\w[\w\d]*)\}/g, (_, v) => eval(v)));

你比较安全*! 相对无所谓

但是,对于evalwindow.eval,要非常小心!!!

这是一个例子:

window.R = {
    toString: _ => 'evil'
};
(window => {
    var R = 'nice';

    //Using evil! erm ... eval()
    alert('${R}'.replace( /\$\{(\w[\w\d]*)\}/g, (_, v) => eval(v)));

    //Using MOAR window.evil! erm ... window.eval()
    alert('${R}'.replace( /\$\{(\w[\w\d]*)\}/g, (_, v) => window.eval(v)));

    //String templates
    alert(`${R}`);

})(window)

它应该显示“nice, evil, nice”。这意味着window.eval 在全局范围内运行,而eval 在本地范围内运行。除了eval() 已经存在的安全问题之外,这是我看到的唯一安全问题。

简而言之,您的方法将与使用字符串模板一样安全。

【讨论】:

  • 模板字符串可以嵌套——这是这里唯一的好例子。其余的只是技术细节/显而易见,我会跳过它们;)我认为其他优点是关于安全性......?
  • @vitaly-t 给我一些时间,因为我还在工作。但是所有这些点对您来说都是显而易见的,但对其他人阅读可能并不明显。
  • 慢慢来,我今天休息。
猜你喜欢
  • 1970-01-01
  • 2017-11-13
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 2017-10-03
相关资源
最近更新 更多