面试题答案
一键面试严格模式与非严格模式下 eval('1 + 2')
的不同
- 作用域影响
- 非严格模式:
eval
执行的代码可以在外部作用域创建变量。例如:
eval('var x = 10'); console.log(x); // 10,在非严格模式下,eval 中的 var 声明会在外部作用域创建变量
- 严格模式:
eval
执行的代码有自己的独立作用域,不会在外部作用域创建变量。例如:
'use strict'; eval('var x = 10'); console.log(x); // ReferenceError: x is not defined,在严格模式下,eval 内的 var 声明仅在 eval 内部作用域有效
- 非严格模式:
- 函数声明提升
- 非严格模式:
eval
内部声明的函数会提升到包含该eval
的作用域顶部。例如:
function outer() { eval('function inner() { return 1; }'); return inner(); } console.log(outer()); // 1,在非严格模式下,eval 内部声明的函数提升到 outer 函数作用域顶部
- 严格模式:
eval
内部声明的函数仅在eval
自身作用域内有效,不会提升到外部作用域。例如:
'use strict'; function outer() { eval('function inner() { return 1; }'); return inner(); } console.log(outer()); // ReferenceError: inner is not defined,在严格模式下,eval 内声明的函数不会提升到 outer 函数作用域
- 非严格模式:
eval
中使用求值表达式可能带来的安全风险
- 代码注入风险:如果
eval
的参数是由用户输入动态生成的,恶意用户可能会注入恶意代码。例如:let userInput = "1; alert('You are hacked!');"; eval(userInput); // 会执行恶意的 alert 代码,存在安全隐患
- 性能问题:
eval
每次执行都需要解析和编译代码,相比直接执行预编译好的代码,性能开销较大。尤其是在循环等频繁执行的场景下,会严重影响性能。
在项目中安全合理地使用 eval
处理复杂求值场景的方法
- 输入验证:
- 确保
eval
的输入是预期的格式和内容。例如,如果预期是一个数学表达式,可以使用正则表达式验证输入是否只包含数字、运算符等合法字符。
function safeEval(expression) { const validExpression = /^[\d+\-*/().\s]+$/.test(expression); if (validExpression) { return eval(expression); } else { throw new Error('Invalid expression'); } } let safeInput = '3 + 5 * 2'; console.log(safeEval(safeInput)); // 13
- 确保
- 使用
new Function
替代:在某些情况下,可以使用new Function
来创建函数并执行求值。new Function
同样接受字符串形式的代码,但它创建的函数作用域更清晰,并且可以限制作用域范围。例如:let mathExpression = 'a + b'; let func = new Function('a', 'b', `return ${mathExpression}`); console.log(func(2, 3)); // 5
- 限制使用场景:仅在确实没有其他替代方案时使用
eval
,并且要对使用eval
的代码进行严格的测试和审查,确保安全性。