eval()
eval()
函数会将传入的字符串当做 JavaScript 代码进行执行。文档请查看MDN
语法
eval(string)
参数
string
一个表示 JavaScript 表达式、语句或一系列语句的字符串。表达式可以包含变量与已存在对象的属性。
返回值
返回字符串中代码的返回值。如果返回值为空,则返回 undefined
。
eval()
是全局对象的一个函数属性。
eval()
的参数是一个字符串。如果字符串表示的是表达式,eval()
会对表达式进行求值。如果参数表示一个或多个 JavaScript 语句,那么eval()
就会执行这些语句。不需要用 eval()
来执行一个算术表达式:因为 JavaScript 可以自动为算术表达式求值。
eval()
的结果是最后一条语句的结果。
示例:
let code = 'alert("Hello Eval")';
eval(code); // Hello Eval
let value = eval('1+1');
console.log(value); // 2
let value1 = eval('let i = 0; ++i');
console.log(value1); // 1
代码字符串可能会比较长,包含换行符、函数声明和变量等。
如果 eval()
的参数不是字符串, eval()
会将参数原封不动地返回。在下面的例子中,String
构造器被指定,而 eval()
返回了 String
对象而不是执行字符串。使用 toString()
,可以绕过这个限制。
示例:
eval("2 + 2"); // returns 4
eval(new String("2 + 2")); // 返回了包含"2 + 2"的字符串对象
let code = new String("2 + 2");
eval(code.toString()); // 4
eval()
内的代码在当前词法环境(lexical environment)中执行,因此它能访问外部变量:
let a = 1;
function f() {
let a = 2;
eval('console.log(a)'); // 2
}
f(); // 执行后,在控制台输出 2
eval()
可以修改外部变量:
let a = 1;
eval("a = 10");
console.log(a); // 10,值被更改了
严格模式下,eval()
有属于自己的词法环境。因此我们不能从外部访问在 eval()
中声明的函数和变量:
// 提示:所有示例都默认启用了严格模式 'use strict'
eval("let x = 5; function f() {}");
console.log(typeof x); // undefined(没有这个变量)
console.log(typeof f); // undefinde 函数 f 也不可从外部进行访问
如果不启用严格模式,eval()
没有属于自己的词法环境,因此我们可以从外部访问变量 x
和函数 f
。
从 ECMAScript 5 起,间接使用 eval()
,会使 eval()
工作在全局作用域下,而不是局部作用域中。
间接使用 eval()
,eval()
代码将执行上下文初始化为全局执行上下文。
示例:
function test() {
var x = 2;
var y = 4;
console.log(eval("x + y")); // 直接调用,使用本地作用域,结果是 6
var geval = eval; // 等价于在全局作用域调用
console.log(geval("x + y")); // 间接调用,使用全局作用域,throws ReferenceError 因为 `x` 未定义
// Error, Uncaught ReferenceError: x is not defined
(0, eval)("x + y"); // 另一个间接调用的例子
}
使用eval
- 如果
eval()
中的代码没有使用外部变量,请以window.eval(...)
的形式调用eval()
:
let x = 1;
function f(){
let x = 5;
window.eval('console.log(x)'); // 1(访问的是全局变量x)
}
f()
- 如果
eval()
中的代码需要访问局部变量,我们可以使用new Function
替代eval()
,并将它们作为参数传递:
let f = new Function('a', 'console.log(a)');
f(5); // 5
new Function
从字符串创建一个函数,并且也是在全局作用域中的。
永远不要使用eval()
如非必要,最好永远不要使用eval()
:
-
安全性问题:如果
eval()
所执行的字符串来自不可信的来源,例如用户输入,那么恶意代码可能会被执行,导致潜在的安全漏洞。 -
性能问题:
eval()
的执行效率相对较低,因为每次调用都需要对字符串进行解析和编译。 -
代码可读性和可维护性:使用
eval()
会使代码变得难以理解和维护,因为代码的逻辑可能隐藏在动态生成和执行的字符串中。 -
eval()
访问外部代码会导致代码压缩率降低。
通常,生产环境的代码会使用代码压缩工具进行压缩,将局部变量重命名为更短的变量(例如 a 和 b 等),以使代码体积更小。在使用了eval()
的情况下,局部变量可能会被eval()
中的代码访问到。因此压缩工具不会对所有可能会被从eval()
中访问的变量进行重命名。这样会导致代码压缩率降低。