深入了解 Eval

人生代码

共 1955字,需浏览 4分钟

 · 2021-03-14

Eval:运行一个代码字符串

内置的eval函数允许执行一串代码。

语法是:

let result = eval(code);

例子:

let code = 'alert("Hello")';
eval(code); // Hello

一个代码串可以很长,包含换行符、函数声明、变量等等。

eval的结果是最后一条语句的结果。

例如:

let value = eval('1+1');
alert(value); // 2
let value = eval('let i = 0; ++i');
alert(value); // 1

eval的代码是在当前的词法环境中执行的,所以它可以看到外部变量:

let a = 1;

function f({
  let a = 2;

  eval('alert(a)'); // 2
}

f();

它也可以改变外部变量:

let x = 5;
eval("x = 10");
alert(x); // 10, value modified

在严格模式下,eval有自己的词法环境。因此,在eval内部声明的函数和变量在外部不可见:

// reminder: 'use strict' is enabled in runnable examples by default

eval("let x = 5; function f() {}");

alert(typeof x); // undefined (no such variable)
// function f is also not visible

如果不使用strict, eval就没有自己的词法环境,所以我们会在外面看到x和f。

使用 eval

在现代编程中,eval的使用非常少。人们常说“eval是邪恶的”。

原因很简单:很久很久以前,JavaScript是一门弱得多的语言,许多事情只能用eval来完成。但十年前,这段时间就过去了。

现在,几乎没有理由使用eval。如果有人正在使用它,他们很有可能用一个现代的语言结构或JavaScript模块来替换它。

请注意,它访问外部变量的能力有副作用。

将局部变量重命名为更短的变量(如a、b等),以使代码更小。这通常是安全的,但如果使用eval,则不是,因为局部变量可以从eval的代码字符串访问。因此,minifier不会对eval中可能可见的所有变量进行重命名。这对代码压缩比有负面影响。

在eval中使用外部局部变量也被认为是一种糟糕的编程实践,因为它使维护代码变得更加困难。

有两种方法可以完全避免这些问题。

如果eval的代码不使用外部变量,请调用eval作为window.eval(…):

这样代码就会在全局作用域中执行:

let x = 1;
{
  let x = 5;
  window.eval('alert(x)'); // 1 (global variable)
}

如果eval代码需要局部变量,将eval改为new Function并将它们作为参数传递:

let f = new Function('a''alert(a)');

f(5); // 5

新函数的构造将在“新函数”语法一章中解释。它从一个字符串创建一个函数,这个字符串也在全局范围内。所以它看不到局部变量。但是,像上面的例子那样,将它们显式地作为参数传递要清楚得多。


浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报