和其他很多解释性语言一样,JavaScript同样可以解释运行由JavaScript源代码组成的字符串,并产生一个值。JavaScript通过全局函数eval()来完成这个工作
 
 

eval(“1+2”),-> 3

动态判断源代码中的字符串是一种很强大的语言特性,几乎没有必要在实际中应用。如果你使用了eval(),你应当仔细考虑是否真的需要使用它。

一、eval()是一个函数还是一个运算符

eval()是一个函数,但由于它已经被当成运算符来对待了。。JavaScript语言的早期版本定义了eval函数,现代JavaScript解释器进行了大量的代码分析和优化。而eval的问题在于,用于动态执行的代码通常来讲不能分析,换句话说,如果一个函数调用了eval,那么解释器将无法对这个函数做进一步优化,而将eval定义为函数的另一个问题是,它可以被赋予其他的名字,var f=eval;那么解释器就无法放心的优化任何调用了f()的函数。而当eval是一个运算符的时候,就可以避免这些问题。

二、eval()

eval()只有一个参数。如果传入的参数不是字符串,它直接返回这个函数。如果参数是字符串,它会把字符串当成JavaScript代码进行编译,如果编译失败者抛出一个语法错误异常。如果编译成功,则开始执行这一段代码,并返回字符串中的最后一个表达式会或语句的值,如果最后一个表达式或语句没有值,则最终返回undefined。如果字符串抛出一个异常,这个异常将把该调用传递给eval()。

关于eval最重要的是,它使用了调用它的变量作用域环境。也就是说,它查找变量的值和定义新变量和函数的操作和局部作用域中的代码完全一样。如果一个函数定义了一个局部变量x,然后调用eval(“x”),它会返回局部变量的值。如果它调用eval(“x=1”),它会改变局部变量的值。如果函数调用了eval(“var y=2;”),它声明了一个新的局部变量y,同样地,一个函数可以通过如下代码声明一个局部变量:

eval(“function f(){return x+1;}”);

如果在最顶层的代码中调用eval,当然,它会作用于全局变量和全局函数。

需要注意的是,传递给eval的字符串必须在语法上将的通,不能通过eval往函数中任意粘贴代码片段,比如:eval(“return ;”)是没有意义的,因为return只有在函数中才起到作用,并且事实上,eval的字符串执行时的上下文环境和调用函数的上下文环境是一样的,这不能使其作为函数的一部分来运行。如果字符串作为一个单独的脚本是有语义的,那么将其传递给eval作参数是完全没有问题的,否则,eval会抛出语法错误异常。

三、全局eval()

eval()具有更改布局变量的能力,这对于JavaScript优化器来说是一个很大的问题。然而作为一种权宜之计,JavaScript解释器针对那些调用了eval的函数所做的优化并不多。但当脚本定义了eval的一个别名,且用另一个名称调用它,JavaScript解释器又会如何工作呢?为了让JavaScript解释器的实现更加简化,ECMAScript3标准规定了任何解释器都不允许对eval赋予别名。如果eval函数通过别名调用的话,则会抛出一个EavlError异常。

实际上,大多数的实现并不是这么做的。当通过别名调用时,eval会将其字符串当成顶层的全局代码来执行。执行的代码可能会定义新的全局变量和全局函数,或者给全局变量赋值,但却不能使用或者修改主调函数中的局部变量,因此,这不会影响到函数内的代码优化。

ECMAScript5是反对使用EavlError的,并且规范了eval的行为,“直接的eval”,当直接使用非限定的“eval”名称来调用eval()函数时,通常称为“直接eval”。直接调用eval()时,它总是在调用它的上下文作用域内执行。其他的间接调用则使用全局对象作为其上下文作用域,并且无法读、写、定义局部变量和函数。下面有一段示例代码:

  1. var geval=eval; //使用别名调用evla将是全局eval
  2. var x="global",y="global"; //两个全局变量
  3. function f(){ //函数内执行的是局部eval
  4. var x="local"; //定义局部变量
  5. eval("x += ' chenged';");//直接使用eval改变的局部变量的值
  6. return x; //返回更改后的局部变量
  7. }
  8. Function g(){ //这个函数内执行了全局eval
  9. var y="local";
  10. geval("y += ' changed';"); //直接调用改变了全局变量的值
  11. return y;
  12. }
  13. console.log(f(),x); //改变了布局变了,输出 “local changed global”
  14. console.log(g(),y); //改变了全局变量,输出 “local global changed”

全局的eval的这些行为不仅仅是处于代码优化其的需要而作出的一种折中方案,它实际上是一种非常有用的特性,它允许我们执行那些对上下文没有任何依赖的全局脚本代码段。真正需要eval来执行代码段的场景并不多见。但当你真的意识到它的必要性的时候,你更可能会使用全局eval而不是局部eval。

四、严格eval()

ECMAScript5严格模式对eval()函数的行为施加了更多的限制,甚至对标识符eval的使用也施加了限制。当在严格模式下调用eval时,或者eval执行的代码段以“Use strict” 指令开始,这里的eval是私有上下文环境中的局部eval。也就是说,在严格模式下,eval执行的代码段可以查询或更改局部变量,但不能在局部作用域中定义新的变量或函数。

此外,严格模式将“eval”列为保留字,这让eval()更像一个运算符。不能用一个别名覆盖eval()函数。并且变量名,函数名。函数参数或者异常捕获的参数都不能取名为eval。

俗话说的好:宝剑锋从磨砺出,梅花香自苦寒来。

出处:http://www.jb51.net/article/40780.htm

JavaScript中的eval()函数详解的更多相关文章

  1. JavaScript中return的用法详解

    JavaScript中return的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 t ...

  2. javascript中的this作用域详解

    javascript中的this作用域详解 Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大.在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉 ...

  3. JavaScript中this的用法详解

    JavaScript中this的用法详解 最近,跟身边学前端的朋友了解,有很多人对函数中的this的用法和指向问题比较模糊,这里写一篇博客跟大家一起探讨一下this的用法和指向性问题. 1定义 thi ...

  4. javascript中=、==、===区别详解

    javascript中=.==.===区别详解今天在项目开发过中发现在一个小问题.在判断n==""结果当n=0时 n==""结果也返回了true.虽然是个小问题 ...

  5. Oracle中的substr()函数 详解及应用

    注:本文来源于<Oracle中的substr()函数 详解及应用> 1)substr函数格式   (俗称:字符截取函数) 格式1: substr(string string, int a, ...

  6. javascript 中合并排序算法 详解

    javascript 中合并排序算法 详解 我会通过程序的执行过程来给大家合并排序是如何排序的...  合并排序代码如下: <script type="text/javascript& ...

  7. JavaScript中数组Array方法详解

    ECMAScript 3在Array.prototype中定义了一些很有用的操作数组的函数,这意味着这些函数作为任何数组的方法都是可用的. 1.Array.join()方法 Array.join()方 ...

  8. JavaScript中的eval()函数

    和其他很多解释性语言一样,JavaScript同样可以解释运行由JavaScript源代码组成的字符串,并产生一个值.JavaScript通过全局函数eval()来完成这个工作. eval(“1+2” ...

  9. JavaScript中的注释问题详解? 部分3

    注释:解释代码的含义,浏览器中不执行. 方便其他程序员了解代码 ,也可以注释自己不需要的代码(开发过程中)! 1. 单行注释 // 用于一行代码上面 2.多行注释 /* */ 用于一段代码上面 或者是 ...

随机推荐

  1. hdu 1203 I NEED A OFFER!(01背包)

    题意:"至少一份offer的最大概率".即求拿不到offer的最小概率 (得到offer的最大概率 = 1 - 反例的最小概率). 状态转移方程:dp[j]= Min(dp[j], ...

  2. FileInputStream 的读取操作

    package xinhuiji_day07; import java.io.File;import java.io.FileInputStream;import java.io.FileNotFou ...

  3. php通过curl下载远程图片实例

    <?php $url = 'http://mf1905.com/upload/video_img/df3074c98ec5124ad47c52ff59f74e04_middle.jpeg'; f ...

  4. erlang的随机数 及 random:uniform()函数

    每次调用会更新进程字典里的random_seed变量,这样在同一个进程内每次调用random:uniform()时,随机数种子都不同,所以生成的随机数都不一样(调用完random:uniform()后 ...

  5. ios中实现对UItextField,UITextView等输入框的字数限制

    本文转载至 http://blog.sina.com.cn/s/blog_9bf272cf01013lsd.html 2011-10-05 16:48 533人阅读 评论(0) 收藏 举报 1.    ...

  6. 九度OJ 1020:最小长方形 (基础题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6019 解决:2849 题目描述:     给定一系列2维平面点的坐标(x, y),其中x和y均为整数,要求用一个最小的长方形框将所有点框在 ...

  7. java 核心技术卷一 知识点

    第九章 集合 1.Iterator和Iterable接口类,作用. 2.Collection接口类,作用. 3.Map接口类,作用.

  8. 【题解】Fence(单调队列)

    [题解]Fence(单调队列) POJ - 1821 题目大意 有\(k\)个粉刷匠,每个粉刷匠一定要粉刷某个位置\(S_i\),一个粉刷匠可以粉刷至多\(l_i\)个位置(必须连续\(l_i\)互不 ...

  9. sap 图标查看

    showicon这个程序很不错,可以显示SAP里所有的ICON(图标). 用事务码SE38直接运行程序:showicon 即可. 显示列表之后,双击任何一个图标可以显示出每一个图标的详细信息.

  10. BFC和haslayout(IE6-7)(待总结。。。)

    支持BFC的浏览器(IE8+,firefox,chrome,safari) Block Formatting Context(块格式化上下文)是W3C CSS2.1规范中的一个慨念,在CSS3中被修改 ...