eval函数

  eval函数接收一个由JavaScript语句组成的字符串,并且返回字符串中最后一条语句的返回值,如果最后一条语句没有返回值,那么eval函数返回undefined。如果传递给eval函数的不是字符串,那么传递什么,eval就返回什么。

调用eval函数的三种情况

  当调用eval函数时,JavaScript会创建新的执行环境,总共有三种情形:

  1 直接调用

  直接调用时,eval函数相关的执行环境属性ThisBinding,LexicalEnvironment,VariableEnvironment的值如下:

  a) ThisBinding是调用eval函数时,调用方执行环境的ThisBinding

  b) LexicalEnvironment是调用eval函数时,调用方执行环境的LexicalEnvironment

  c) VariableEnvironemnt是调用eval函数时,调用方执行环境的VariableEnvironment

  假设有如下JavaScript代码(f在全局环境下被调用):

function f() {
var i = 1; eval("var y = 2; i = 3");
  
  alert(y);
} f();

当eval函数被调用时,执行环境栈如下图所示:

  需要注意的是,当新建一个执行环境时要进行标识符绑定,绑定的标识符放到执行环境VariableEnvironment指向的Lexical Environment中。由于eval函数的VariableEnvironment与调用方(即调用eval的函数f)的VariableEnvironment指向同一个Lexical Environment,因此,在eval中声明的局部变量y被绑定到调用方的Lexical Environment中,这导致当eval函数调用结束,与eval相关的执行环境被弹出栈顶,而在eval中声明的局部变量y在函数f中仍然可以访问得到。因此,上面代码中alert会显示2,而不是报错。

  2 间接调用

  所谓间接调用,即将eval赋值给另一个变量后在调用,如下面代码所示:

var g = eval;
g("var y = 1;");

  间接调用也会创建新的执行环境,不同之处在于新执行环境的ThisBinding,LexicalEnvironment,VariableEnvironment的值不同:

  a) ThisBinding为全局对象

  b) LexicalEnvironment为全局执行环境的的LexicalEnvironment

  c) VariableEnvironment为全局执行环境的VariableEnvironment

  假如有下面的代码:

function f() {
var i = 1; var gEval = eval;
gEval("var y = 2; i = 3");
  
  alert(y); } f();

当调用gEval时,执行环境栈如下图所示:

  可以看到,在gEval当中声明的变量都绑定到了全局执行环境当中,需要注意的是,gEval当中的变量i并不是引用的函数f的变量i,因为从gEval的作用域链访问不到函数f的局部变量i,此时gEval中的变量i就等价于没有使用关键字var声明了一个全局变量。函数f的alert语句仍然显示2,只是此时访问的y是全局环境中的变量y。

  3 严格模式下的eval

  在严格模式下,eval的LexicalEnvironment,VariableEnvironment指向属于eval自己的Lexcial Environment,而不是调用方的Lexical Environment,但是ThisBinding还是调用方的ThisBinding。同时,在严格模式下如果eval直接调用,那么eval的Lexical Environment的outer指针指向调用方的Lexical Environment,否则,如果是间接调用,那么eval的Lexical Environment的outer指针指向全局环境的Lexical Environment。

  假如有如下代码:

"use strict"; //使用严格模式

function f() {
var i = 1; eval("var y = 2; i = 3");
  
  alert(y); } f();

当调用eval时,执行环境栈如下图所示:

  从图可以看到,eval中声明的局部变量y被绑定到自己的Lexical Environment中,eval中的i访问的是函数f声明的局部变量i。由于变量y被绑定在eval自己的Lexical Environment中,因此当eval运行结束,相关的执行环境被弹出栈顶之后,函数f是访问不到变量y的,因此alert要报错。

IE中的eval

  IE9之前,无论eval是直接调用还是间接调用,eval都当成直接调用处理,如果需要有间接调用的效果,可以使用IE提供的execScript函数。

参考资料:

JavaScript权威指南

ECMA-262

JavaScript当中的eval函数的更多相关文章

  1. JavaScript中的eval()函数

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

  2. java ScriptEngine 使用 (支持JavaScript脚本,eval()函数等)

    Java SE 6最引人注目的新功能之一就是内嵌了脚本支持.在默认情况下,Java SE 6只支持JavaScript,但这并不以为着Java SE 6只能支持JavaScript.在Java SE ...

  3. JavaScript中的eval()函数详解

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

  4. javascript中的eval函数

    eval()只有一个参数,如果传入的参数不是字符串,则直接返回这个参数.否则会将字符串当成js代码进行编译,如果编译失败则抛出语法错误(SyntaxError)异常.如果编译成功则开始执行这段代码,并 ...

  5. javascript中的eval()函数应用以及要点

    eval是干嘛用的?eval是直接将一段字符串作为参数,交给JS引擎预编译器进行动态分析并执行代码.如下: //调试台输出,你可以理解为console.log,再不理解就理解成alert也没事 var ...

  6. JavaScript中Eval()函数的作用

    这一周感觉没什么写的,不过在研究dwz源码的时候有一个eval()的方法不是很了解,分享出来一起学习 -->首先来个最简单的理解 eval可以将字符串生成语句执行,和SQL的exec()类似. ...

  7. Javascript eval()函数 基础回顾

    如果您想详细了解ev al和JSON请参考以下链接: eval  :https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Glo ...

  8. JavaScript中eval()函数

    eval调用时,实例为eval( "( javascript代码 )" ), eval() 函数可将字符串转换为代码执行,并返回一个或多个值.

  9. eval函数的工作原理

    如果您想详细了解eval和JSON请参考以下链接: eval  :https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Glob ...

随机推荐

  1. mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in

    从字面的意思上说:这个函数要被弃用,请使用 mysqlli 或者是 PDO 代替 然后就查手册发现没说,大家一定要查官方最新的手册

  2. hdfs的实现机制和文件系统概念

    1.HDFS的诞生背景: 数据量太大,在一个结点(机器)存不下.所以需要分布式存储,HDFS就是hadoop的分布式文件系统,来存储分布式数据. 2.共享文件系统也是一种分布式存储但有缺点:1.并发差 ...

  3. List myList=new ArrayList()的理解

    ArrayList不是继承List接口,是实现了List接口.你写成ArrayList arrayList = new ArrayList();这样不会有任何问题.和List list = new A ...

  4. cocos2d安卓android长音效播放不完全

    是因为安卓限制了音效的内存,一般把mp3的比特率压缩一下.就可以搞定了.

  5. 统计的基本操作语法 <第五篇>

    1.创建统计语法: CREATE STATISTICS statistics_name ON { table_or_indexed_view_name } ( column [ ,...n ] ) [ ...

  6. Android,监控ContentProvider的数据改变

    有时候应用中需要监听ContentProvider的改变并提供响应,这时候就要利用ContentObserver类了 不管是ContentProvider中实现的,insert,delete,upda ...

  7. 【转】使用adb命令对手机进行截屏(截图)保存到电脑,SDCard

    原文网址:http://blog.csdn.net/huangyabin001/article/details/29198367 adb shell /system/bin/screencap -p  ...

  8. HDu 5433 Xiao Ming climbing (BFS)

    题意:小明因为受到大魔王的诅咒,被困到了一座荒无人烟的山上并无法脱离.这座山很奇怪: 这座山的底面是矩形的,而且矩形的每一小块都有一个特定的坐标(x,y)和一个高度H. 为了逃离这座山,小明必须找到大 ...

  9. 使用cx_Freeze 将python3代码打包成.exe程序

    在这里分享一下如何在py3下使用cx_Freeze打包pyqt5的程序 首先吐槽下,深深鄙视一下百度,各种百度各种没有,之前我在py2.7下使用pyqt4开发过一个小软件,用的是py2exe进行打包的 ...

  10. poj 1088 滑雪问题

    滑雪问题 import java.util.Scanner; public class Main{ static int a[][],r,c; public static void main(Stri ...