eval函数
Eval: run a code string
Eval:执行字符串内的代码
The built-in eval function allows to execute a string of code.
内建(built-in)函数eval让我们能够执行字符串内的代码。
The syntax is:
语法如下:
1 | let result = eval(code); |
For example:
比如:
1 | let code = 'alert("Hello")'; |
A string of code may be long, contain line breaks, function declarations, variables and so on.
这样的字符串可能比较长,其中包含换行符(line breaks)、函数声明(function declarations)和变量,等等。
The result of eval is the result of the last statement.
eval返回字符串中最后一个语句的结果。
For example:
比如:
1 | let value = eval('1+1'); |
1 | let value = eval('let i = 0; ++i'); |
The eval’ed code is executed in the current lexical environment, so it can see outer variables:
字符串内的代码在当前词法环境(lexical environment)下执行,因此能访问外部变量:
1 | let a = 1; |
It can change outer variables as well:
我们在字符串中也能对外部变量重新赋值:
1 | let x = 5; |
In strict mode, eval has its own lexical environment. So functions and variables, declared inside eval, are not visible outside:
严格模式(strict mode)下,eval有属于自己的词法环境,因此我们不能访问在该函数中声明的函数和变量:
1 | // reminder: 'use strict' is enabled in runnable examples by default |
Without use strict, eval doesn’t have its own lexical environment, so we would see x and f outside.
如果不用严格模式,eval没有属于自己的词法环境,因此我们能在外部访问x变量和f函数。
Using “eval”
使用“eval”
In modern programming eval is used very sparingly. It’s often said that “eval is evil”.
现代编程中,eval已不常用。人们经常说“eval is evil”.
The reason is simple: long, long time ago JavaScript was a much weaker language, many things could only be done with eval. But that time passed a decade ago.
原因很简单:JavaScript曾经很难用,很多操作只能用eval来完成,不过这是十年前的事了。
Right now, there’s almost no reason to use eval. If someone is using it, there’s a good chance they can replace it with a modern language construct or a JavaScript Module.
如今几乎找不到理由来用eval了。如果有人用,那么可能要换用现代语言构造(language construct)或者JavaScript Module了。
Please note that its ability to access outer variables has side-effects.
注意,eval访问外部函数会产生副作用(side-effects)。
Code minifiers (tools used before JS gets to production, to compress it) rename local variables into shorter ones (like a, b etc) to make the code smaller. That’s usually safe, but not if eval is used, as local variables may be accessed from eval’ed code string. So minifiers don’t do that renaming for all variables potentially visible from eval. That negatively affects code compression ratio.
代码压缩工具(minifier)将局部变量重命名,使其更短(比如a和b,等等),这样代码体积就变小了。
注:压缩工具压缩代码,用于JS进入生产环境前。
Using outer local variables inside eval is also considered a bad programming practice, as it makes maintaining the code more difficult.
在eval内获取外部局部变量不是良好的编程习惯,这会使维护代码变得更加困难。
There are two ways how to be totally safe from such problems.
有两种方法来完全避免这类问题。
If eval’ed code doesn’t use outer variables, please call eval as window.eval(...):
如果字符串中的代码不访问外部变量,调用window.eval(...):
This way the code is executed in the global scope:
这样,代码便会在全局作用域(global scope)内执行:
1 | let x = 1; |
If eval’ed code needs local variables, change eval to new Function and pass them as arguments:
如果eval内代码需要访问局部变量,我们可以使用new Function,将此变量作为参数传递。
1 | let f = new Function('a', 'alert(a)'); |
The new Function construct is explained in the chapter info:new-function. It creates a function from a string, also in the global scope. So it can’t see local variables. But it’s so much clearer to pass them explicitly as arguments, like in the example above.
对于new Function,可参考info:new-function。该构造函数接收字符串,返回位于全局作用域下的函数,因此该函数无法访问局部变量。然而如以上一例,向new Function显式传递该变量会使代码变得容易理解。
Summary
总结
A call to eval(code) runs the string of code and returns the result of the last statement.
eval(code)会执行字符串内的代码并返回最后一个语句的结果。
Rarely used in modern JavaScript, as there’s usually no need.
Can access outer local variables. That’s considered bad practice.
Instead, to
evalthe code in the global scope, usewindow.eval(code).Or, if your code needs some data from the outer scope, use
new Functionand pass it as arguments.现代JavaScript不常用该函数,通常也没必要用。
该函数可以访问外部局部变量,但这不是个好习惯。
取而代之,使用
window.eval(code)以使代码在全局作用域下执行。或者,如果代码需要从外部作用域获取数据,请使用
new Function并将该数据作为参数传递给函数。