在线文档教程

eval

eval

eval()函数会将传入的字符串当做JavaScript代码进行执行。

语法

eval(string)

参数

string一串表示JavaScript表达式,语句, 或者是一系列语句的字符串。表达式可以包括变量以及已存在对象的属性。

返回值

执行指定代码之后的返回值。如果返回值为空,返回undefined

描述

eval()是全局对象的一个函数属性。

eval()的参数是一个字符串。如果字符串表示的是表达式,eval()会对表达式进行求值。如果参数表示一个或多个JavaScript语句, 那么eval()就会执行这些语句。注意不要用eval()来执行一个四则运算表达式;因为 JavaScript 会自动为四则运算求值并不需要用eval来包裹。

如果要将算数表达式构造成为一个字符串,你可以用eval()在随后对其求值。比如,假如你有一个变量 x ,你可以通过一个字符串表达式来对涉及x的表达式延迟求值,将 "3 * x + 2",存储为变量,然后在你的脚本后面的一个地方调用eval()。

如果eval()的参数不是字符串,eval()将会将参数原封不动的返回。在下面的例子中,字符串构造器被指定,eval()返回了字符串对象而不是对字符串求值。

eval(new String('2 + 2') // returns a String object containing "2 + 2" eval('2 + 2' // returns 4

你可以使用通用的的方法来绕过这个限制,如使用toString()

var expression = new String('2 + 2' eval(expression.toString()

如果你间接的使用 eval(), 如通过一个引用来调用它而不是直接的调用eval。 从ECMAScript 5起它工作在全局作用域而不是局部作用域中;这就意味着,例如,下面的代码的作用声明创建一个全局函数,并且geval中的这些代码在执行期间不能在被调用的作用域中访问局部变量。

function test() { var x = 2, y = 4; console.log(eval('x + y')  // Direct call, uses local scope, result is 6 var geval = eval; // equivalent to calling eval in the global scope console.log(geval('x + y') // Indirect call, uses global scope, throws ReferenceError because `x` is undefined   (0, eval)('x + y' // another example of Indirect call }

避免在不必要的情况下使用eval

eval() 是一个危险的函数, 他执行的代码拥有着执行者的权利。如果你用eval()运行的字符串代码被恶意方(不怀好意的人)操控修改,您可能会利用最终在用户机器上运行恶意方部署的恶意代码,并导致您失去您的网页或者扩展程序的权限。更重要的是,第三方代码可以看到某一个eval()被调用时的作用域,这也有可能导致一些不同方式的攻击。相似的Function就是不容易被攻击的。

eval()的运行效率也普遍的比其他的替代方案慢,因为他会调用js解析器,即便现代的JS引擎中已经对此做了优化。

在常见的案例中我们都会找更安全或者更快的方案去替换他

访问成员属性

你不应该去使用eval()来将属性名字转化为对象的属性属性。考虑下面的这个例子,被访问对象的属性在它被执行之前都会未知的。这里虽然可以被处理用eval:

var obj = { a: 20, b: 30 }; var propName = getPropName( // returns "a" or "b" eval( 'var result = obj.' + propName

但是,这里并不是必须得使用eval()。事实上,这里并不支持这样使用。可以使用属性访问器进行代替,它更快而且更安全:

var obj = { a: 20, b: 30 }; var propName = getPropName( // returns "a" or "b" var result = obj[ propName ]; // obj[ "a" ] is the same as obj.a

你还可以使用这个方法去访问子代的属性。如下:

var obj = {a: {b: {c: 0}}}; var propPath = getPropPath( // returns e.g. "a.b.c" eval( 'var result = obj.' + propPath

这里则通过规避使用Eval()实现了循环获取子代的属性:

function getDescendantProp(obj, desc) {   var arr = desc.split('.'   while (arr.length) { obj = obj[arr.shift()]; }   return obj; } var obj = {a: {b: {c: 0}}}; var propPath = getPropPath( // returns e.g. "a.b.c" var result = getDescendantProp(obj, propPath

同样的方法也可实现设置子代的属性值:

function setDescendantProp(obj, desc, value) {   var arr = desc.split('.'   while (arr.length > 1) { obj = obj[arr.shift()]; }   obj[arr[0]] = value; } var obj = {a: {b: {c: 0}}}; var propPath = getPropPath( // returns e.g. "a.b.c" var result = setDescendantProp(obj, propPath, 1 // test.a.b.c will now be 1

使用函数而非代码段

JavaScript拥有first-class functions,这意味着你可以将函数直接作为参数传递给其他接口,并将他们保存在变量中或者对象的属性中等等,很多DOM的API都用这种思路进行设计,你也可以(或者应该)这样子设计你的代码:

// instead of setTimeout(" ... ", 1000) use: setTimeout(function() { ... }, 1000 // instead of elt.setAttribute("onclick", "...") use: elt.addEventListener('click', function() { ... } , false

Closures 也可以作为一种创建参数化函数而不连接字符串的方法.

解析 JSON(将字符串转化为JavaScript对象)

如果你在调用eval()传入的字符串参数中更包含数据(如:一个数组“[1,2,3]”)而不是代码,你应该考虑将其转换为JSON对象,这允许你用JavaScript语法的子集来表示数据。在扩展中下载JSON和JavaScript

提示:因为JSON语法子集相对于JavaScript语法子集比较有局限性,很多在JavaScript中可用的特性在JSON中就不起作用了,如:后缀都好JSON就不支持,并且,对象中的属性名在JSON中必须用引号括起来,所以在使用JSON序列化将字符串转化为JSON对象时需确认字符串格式

尽量传递数据而非代码

例如,设计用于擦除网页内容的扩展可能会在XPath中定义规则,而不是JavaScript代码。

执行这段代码应加以权限限制

如果你必须执行这段代码, 应考虑以更低的权限运行. 这建议主要应用于Components.utils.evalInSandbox 可扩展的标记语言

例子

举例: 使用eval

在下面的代码中,两种声明都返回了42。第一种是对字符串 "x + y + 1"求值;第二种是对字符串 "42"求值。

var x = 2; var y = 39; var z = '42'; eval('x + y + 1' // returns 42 eval(z // returns 42

举例: 使用 eval 对JavaScript声明求值

下面的例子使用eval() 对str字符串求值。这个字符串包含了JavaScript声明,如果x等于5,就打开一个Alert 对话框,然后对 z 赋值。 否则就对z赋值0。 当第二个声明被执行, eval 将会将str表达式执行,然后会对声明集合求值,并将返回值赋值给z。

var x = 5; var str = "if (x == 5) {console.log('z is 42' z = 42;} else z = 0;"; console.log('z is ', eval(str)

最后的表达式被计算

eval 将会返回对最后一个表达式的求值结果。

var str = 'if ( a ) { 1 + 1; } else { 1 + 2; }'; var a = true; var b = eval(str // returns 2 console.log('b is : ' + b a = false; b = eval(str // returns 3 console.log('b is : ' + b

eval 作为字符串定义函数需要“(”和“)”作为前缀和后缀

var fctStr1 = 'function a() {}' var fctStr2 = '(function a() {})' var fct1 = eval(fctStr1) // return undefined var fct2 = eval(fctStr2) // return a function

规范

SpecificationStatusComment
ECMAScript 1st Edition (ECMA-262)StandardInitial definition.
ECMAScript 5.1 (ECMA-262)The definition of 'eval' in that specification.Standard
ECMAScript 2015 (6th Edition, ECMA-262)The definition of 'eval' in that specification.Standard
ECMAScript Latest Draft (ECMA-262)The definition of 'eval' in that specification.Living Standard

浏览器兼容性

FeatureChromeEdgeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support(Yes)(Yes)(Yes)(Yes)(Yes)(Yes)

FeatureAndroidChrome for AndroidEdgeFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic support(Yes)(Yes)(Yes)(Yes)(Yes)(Yes)(Yes)