JavaScript eval():执行代码字符串

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()

  1. 安全性问题:如果 eval() 所执行的字符串来自不可信的来源,例如用户输入,那么恶意代码可能会被执行,导致潜在的安全漏洞。

  2. 性能问题:eval() 的执行效率相对较低,因为每次调用都需要对字符串进行解析和编译。

  3. 代码可读性和可维护性:使用 eval() 会使代码变得难以理解和维护,因为代码的逻辑可能隐藏在动态生成和执行的字符串中。

  4. eval()访问外部代码会导致代码压缩率降低。
    通常,生产环境的代码会使用代码压缩工具进行压缩,将局部变量重命名为更短的变量(例如 a 和 b 等),以使代码体积更小。在使用了 eval() 的情况下,局部变量可能会被 eval() 中的代码访问到。因此压缩工具不会对所有可能会被从 eval() 中访问的变量进行重命名。这样会导致代码压缩率降低。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值