eval()、new Function()(高级)eval()new Function()在本章中,我们将介绍两种动态评估代码的方法:eval() 和 new Function()。
eval()给定一个包含 JavaScript 代码的字符串 str,eval(str) 会评估该代码并返回结果。
> eval('2 ** 4')
16调用 eval() 有两种方式:
“不通过函数调用”指的是“任何看起来不像 eval(···) 的东西”。
eval.call(undefined, '···')(使用 函数的 .call() 方法)eval?.() ()(使用 可选链)(0, eval)('···')(使用 逗号运算符)globalThis.eval('···')const e = eval; e('···')以下代码说明了区别:
globalThis.myVariable = 'global';
function func() {
const myVariable = 'local';
// Direct eval
assert.equal(eval('myVariable'), 'local');
// Indirect eval
assert.equal(eval.call(undefined, 'myVariable'), 'global');
}在全局上下文中评估代码更安全,因为代码可以访问的内部结构更少。
new Function()new Function() 创建一个函数对象,并按如下方式调用:
const func = new Function('«param_1»', ···, '«param_n»', '«func_body»');上一条语句等价于下一条语句。请注意,«param_1» 等不再位于字符串字面量中。
const func = function («param_1», ···, «param_n») {
«func_body»
};在下一个示例中,我们创建了两次相同的函数,第一次通过 new Function(),第二次通过函数表达式。
const times1 = new Function('a', 'b', 'return a * b');
const times2 = function (a, b) { return a * b };尽可能避免动态评估代码。
很多时候,JavaScript 本身就足够动态,因此您不需要 eval() 或类似的东西。在以下示例中,我们使用 eval()(A 行)所做的事情在没有它的情况下也可以实现(B 行)。
const obj = {a: 1, b: 2};
const propKey = 'b';
assert.equal(eval('obj.' + propKey), 2); // (A)
assert.equal(obj[propKey], 2); // (B)如果您必须动态评估代码:
new Function() 而不是 eval():它始终在全局上下文中执行其代码,并且函数为评估的代码提供了一个干净的接口。eval 而不是直接 eval:在全局上下文中评估代码更安全。