eval
eval()主要用来解释执行由js代码组成的字符串。接收一个参数,如果参数不为字符串,直接返回传递的参数。如果参数是字符串,它就会将字符串当成js代码进行编译,编译失败会抛出SyntaxError异常,编译成功就执行这段代码(即传递的字符串作为一个单独的脚本是有语义的)。并返回最后一个表达式或语句的值,如果最后一个表达式或语句没有值,则返回undefined。
1、eval()使用调用它的变量作用域环境。即全局作用域环境中调用时,eval作用于全局变量和全局函数;局部变量作用域环境中调用时,就会作用于局部变量和局部函数。
1 /* 全局作用域 */ 2 var x = 1; 3 eval("function fun() {return x+1;}"); 4 fun() //动行结果:2 5 6 /* 局部作用域 */ 7 var x = 2; 8 function fun2() { 9 var x = 10; 10 eval("x += 2"); 11 alert(x); // 12 12 } 13 alert(x); // 2
2、全局eval():为了让js解释器的实现更加简化,ES3标准规定了任何解释器都不允许对eval()赋予别名。如果eval()函数通过别名调用的话,则会抛出EvalError异常。实际上大多数得实现在通过别名调用时,eval()会将其字符串当成顶层的全局代码来执行。即使在函数中调用时,也不能修改函数中的局部变量,而会直接作用于全局变量或函数。
ES5是反对使用EvalError的,并且规范了eval的行为。当直接使用非限定的eval名称来调用eval()函数时,通常称为"直接eval"(direct eval)。直接调用eval()时,它总是在调用它的上下文作用域内执行。其它间接调用则使用全局对象作为其上下文作用域,并且无法读,写,定义局部变量和函数。看下面代码:
1 var geval = eval; 2 var x = "global", 3 y = "global"; 4 function fun() { 5 var x = "local"; 6 eval("x += ' changed';"); 7 return x; 8 } 9 10 function gFun() { 11 var y = "local"; 12 geval("y += ' changed';"); 13 return y; 14 } 15 16 console.log(fun(), x); //local changed global 17 console.log(gFun(), y); //local global changed
ps:ie9之前的版本,当通过别名调用eval()时并不是全局eval(),仅仅将其当作局部的eval来调用。但IE定义execScript()的全局函数来完成全局eval的功能。与eval()不同的时,这个家伙总是返回null;
3、严格eval():ES5严格模式,对eval()函数的行为施加了更多的限制,甚至对标识符eval的使用也添加了限制。在严格模式下调用eval()时,或者eval()扫行的代码段以"use strict"指令开始,这里的eval()是私有上下文环境中的局部eval。即在严格模式下,eval扫行的代码段可以查询或更改局部变量,但不能在局部作用域中定义新的变量或函数。
---摘自《JavaScript 权威指南》第6版