模板文字对我来说有点像eval,它经常被引用using eval is a bad idea。
我并不关心performance of template literals,但我担心注射攻击(以及我可能没想到的其他安全问题)。
修改
An example of something that feels odd to me
let ii = 1;
function counter() {
return ii++;
}
console.log(`${counter()}, ${ii++}, ${counter()}`);
哪个输出
1,2,3
模板文字在全球范围内产生副作用。既可以通过函数直接使用。
修改2
An example indicating the saferness of template literals
let ii = 1;
let inc = function() { ii++; }
console.log('Starting: ' + ii);
let input = prompt('Input something evil (suggestion: inc() or ii++)');
console.log(`You input: ${input}`);
console.log('After template literal: ' + ii);
eval(input);
console.log('After eval: ' + ii);
如果您在提示时输入ii++
,则会记录
开始:1
您输入:ii + = 1
模板文字后:1
评估后:2
编辑3
我开始研究ECMAScript规范
虽然我没有仔细研究细节,但感觉模板文字的指定比eval更安全。
答案 0 :(得分:25)
与eval
的一个区别是模板文字在编译时被解析,而eval
的参数仅在运行时被解析,执行eval
时。
与此相关的是,eval
可以获得动态构建的参数,而模板文字是...... literal :它不能存储为模板变量< / em>,你可以动态构建,移动并最终解析:没有“模板变量”数据类型。标记函数实际上并不将模板变量作为参数获取,而是将其解析为组件,这在编译时是已知的。
使用eval
可以解决此问题:
var code = prompt('enter some evil code');
eval(code);
但是模板文字无法做到这一点:
var literal = prompt('enter some evil template literal');
tag literal; // there is no data type or syntax for this.
`${literal}`; // and this just gives you the entered string.
可能的是:
var str = prompt('enter some string');
tag`${str}`;
但这不会导致不必要的代码执行,至少不会比这更糟糕:
var str = prompt('enter some string');
myfunc(str);
任何函数调用必须已经在模板文字中按字面编码。字符串变量的值不能改变它。模板文字无法调用变量函数。这样:
`${func(str)}`;
...只会调用func
和该函数。它由程序员选择。
话虽如此,这仍然是可能的:
var func = prompt ("enter some evil function name (suggestion: 'alert')");
var param = prompt ("now provide an argument for " + func);
`${window[func](param)}`;
但很明显,程序愿意开启了在全局对象上执行任何功能的可能性。事实上,你正在接近eval
的邪恶。
请注意,使用以下方法可以达到同样的效果:
window[name](param);
如评论所述,那么你也可以制作这个模板文字:
`eval(str)`;
...所以邪恶的部分不是在模板文字中,而是泛型函数调用你有设计在其中。为此,您不需要模板文字或eval
,但需要一个糟糕的程序员; - )
你举了这个例子:
let ii = 1;
function counter() {
return ii++;
}
console.log(`${counter()}, ${ii++}, ${counter()}`);
这将执行您的counter
函数,但与eval
的区别在于字符串文字在设计时已经存在,并且无法在运行时构建。此代码设计以增加您的计数器,并且与以下内容完全不同:
console.log(counter() + ', ' + (ii++) + ', ' + counter());
要强调编译/运行时解析的区别,请注意您无法使用没有有效语法的模板文字运行代码。
比较这两个脚本:
alert('press OK');
eval('alert("hello)');
和
alert('press OK');
`${alert("hello)}`;
请注意语法错误。第一个脚本只会在解析eval
的参数时在运行时发现语法错误,而第二个脚本甚至不会运行,并立即给出语法错误。
更准确地说,eval
执行一个新脚本,具有自己的编译和运行阶段。模板文字与其他代码一样被解析/编译。
答案 1 :(得分:2)
我认为 eval 和模板文字之间存在一个很大的区别。
eval 可以评估代码中无法直接显示的动态表达式。这使得它很危险,因为您可以评估可能出现的任何字符串 来自任何地方:客户/第三方/数据库......
但是模板文字,
的情况不同例如,这适用于 eval
function doSomething() {
console.log('HELLO!');
}
// This will work.
var expression = 'doSomething()';
eval(expression);
&#13;
但这不适用于模板文字
// This will not.
`${expression}`;
您需要静态插入表达式才能使其正常工作
// To make it work you need to insert it statically.
`${doSomething()}`;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
答案 2 :(得分:1)
模板文字会自动转义引号,如果这是您所关注的内容。它们也不会评估或执行任何操作,它们会将您输入的任何内容转换为字符串。如果您担心SQL注入尝试使用模板文字,那么您将看到它们被转义。
你应该避免使用eval,除非你有非常好的理由来使用它,你真的知道你需要它来实现你的目标。否则最好避免。