eval()只有一个参数,如果传入的参数不是字符串,它直接返回这个参数。如果参数是字符串,它会把字符串当成javascript进行编译(parse),如果编译失败则抛出一个语法错误(SyntaxError)。如果编译成功,则开始执行这段代码,并返回字符串中最后一个表达式或语句的值,如果最后一个表达式没有语句或者值,则最终返回undefined。如果字符串抛出一个异常,这个异常把该调用的传给eval()
关于eveal()最重要的是,它使用了调用它的变量作用域环境,也就是说,它查找变量的值和定义新变量和函数的操作和局部的代码作用域中的代码一样。如果一个函数定义了一个局部变量x,然后调用了eval("x"),它会返回局部变量的值。如果它调用eval("x=1"),它会改变局部变量的值。如果函数调用了eval("var y=3;")它声明一个新的局部变量y。同样的,一个函数可以通过如下代码声明一个局部函数:
eval("function f(){return x+1;}");
如果最顶层的代码中调用了eval()。当然它会作用于全局变量和全局函数。
ii.全局eval()
eval()具有改变局部变量的能力,这对javascript优化器来说,是一个很大的问题,然而作为一种权宜之计,javascript征对那行调用了eval()函数所做的优化并不多。但当脚本定义了一个别名,并且用令一个名称来调用它,javascript解释器又如何工作呢,为了javascript解释器更加简化。ECMAScipt3标准规定了任何解释器都不允许对eval()赋予别名。如果eval()使用别的别名来调用的话,则会抛出EvalError异常。
实际上,大多数的实现并不是这样做的。当通过别名调用时,eval()会将其字符串当成顶层的全局代码来执行。执行代码可能会定义新的全局变量和全局函数。执行的代码可能会定义新的全局变量和全局函数,或者给全局变量赋值。但却不能修改或修改主调函数中的局部变量,因此这不会影响到函数内的代码优化。
ECMAScript5是反对使用EvalError的,并且规范了eval()的行为。“直接的eval”,当直接使用非限定的“eval”名称,来调用eval()函数时,它总共是在它的上下文作用域内支线。其它间接调用则使用全局函数为其上下文作用域。并且无法读、写、定义局部变量和函数。下面有一段代码实例:
复制代码 代码如下:
var geval = eval; //使用别名调用eval将是全局eval
var x = "global",
y = "global"; //两个全局变量
function f() { //函数内执行的局部eval
var x = "local" //定于局部变量
eval("x += 'changed';"); //直接eval更改了局部变量的
return x; //返回更改后的局部变量
}
function g() { //这个函数执行了全局eval
var y = "local" //定义了局部变量
geval("y += 'changed';"); //间接改变了局部变量的值
return y; //返回未更改的局部变量
}
console.log(f(), x); //更改了局部变量,输出local changed global
console.log(g(), y); //更改了全局变量,输出local globalchanged
13.其它运算符。
javascript支持很多其它各种各样的运算符。
i.条件运算符(?:)
条件运算符是javascript中的唯一一个三元运算符。通常这个运算符写成"?:",这个运算符拥有三哥操作数,第一个操作数在"?"之前,第二个操作数在“?”和":"之间。第三个操作数早在":"之后,例如