JavaScript当中的eval函数
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函数的更多相关文章
- JavaScript中的eval()函数
和其他很多解释性语言一样,JavaScript同样可以解释运行由JavaScript源代码组成的字符串,并产生一个值.JavaScript通过全局函数eval()来完成这个工作. eval(“1+2” ...
- java ScriptEngine 使用 (支持JavaScript脚本,eval()函数等)
Java SE 6最引人注目的新功能之一就是内嵌了脚本支持.在默认情况下,Java SE 6只支持JavaScript,但这并不以为着Java SE 6只能支持JavaScript.在Java SE ...
- JavaScript中的eval()函数详解
和其他很多解释性语言一样,JavaScript同样可以解释运行由JavaScript源代码组成的字符串,并产生一个值.JavaScript通过全局函数eval()来完成这个工作 eval(“1 ...
- javascript中的eval函数
eval()只有一个参数,如果传入的参数不是字符串,则直接返回这个参数.否则会将字符串当成js代码进行编译,如果编译失败则抛出语法错误(SyntaxError)异常.如果编译成功则开始执行这段代码,并 ...
- javascript中的eval()函数应用以及要点
eval是干嘛用的?eval是直接将一段字符串作为参数,交给JS引擎预编译器进行动态分析并执行代码.如下: //调试台输出,你可以理解为console.log,再不理解就理解成alert也没事 var ...
- JavaScript中Eval()函数的作用
这一周感觉没什么写的,不过在研究dwz源码的时候有一个eval()的方法不是很了解,分享出来一起学习 -->首先来个最简单的理解 eval可以将字符串生成语句执行,和SQL的exec()类似. ...
- Javascript eval()函数 基础回顾
如果您想详细了解ev al和JSON请参考以下链接: eval :https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Glo ...
- JavaScript中eval()函数
eval调用时,实例为eval( "( javascript代码 )" ), eval() 函数可将字符串转换为代码执行,并返回一个或多个值.
- eval函数的工作原理
如果您想详细了解eval和JSON请参考以下链接: eval :https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Glob ...
随机推荐
- windows新的数据类型
1.简单重定义的 如LPCSTR只字符串,只是名字不同 2.句柄类型 H开头的句柄 3.结构体类型 如对话框 4.重新更名一方面为了32位->64位升级时带来的麻烦 typedef unsign ...
- Truncate Table user
Truncate Table 百科名片 Truncate是一个能够快速清空资料表内所有资料的SQL语法.并且能针对具有自动递增值的字段,做计数重置归零重新计算的作用. 目录 语法 参数 注释 示例 ...
- HTML5 video 事件
1.获取视频时间长度 当视频载入video后,使用 onloadedmetadata 事件获取视频的时间长度. video.onloadedmetadata = function () { var v ...
- Java笔记--Java的List、Iterator用法
1. List的使用 准备知识: List继承自Collection接口.List是一种有序集合,List中的元素可以根据索引(顺序号:元素在集合中处于的位置信息)进行取得/删除/插入操作. 跟Set ...
- iOS -多字体混合
label 加下划线 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, 300, 100)]; label.b ...
- Effective Java2读书笔记-类和接口(四)
第19条:接口只用于定义类型 这一条就举了一个反例,说有些接口中只包含常量.这是对接口的不良使用.要实现相同的功能,应该使用不可实例化的工具类(第4条说过). public class Physica ...
- 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端
原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端 chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车 ...
- GET: https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login? loginicon=true &uuid=odcptUu2JA==&tip=0
GET: https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login? loginicon=true &uuid=odcptUu2JA==&am ...
- Intel处理器 天梯图
http://www.mydrivers.com/zhuanti/tianti/cpu/ 更新日期: 2016年6月 纠 错: wenq#mydrivers.com Core 2及之前 ...
- mybatis和hibernate对比
Hibernate是一个数据库表和java对象之间完全映射的框架,java开发人员直接对java对象操作,而不对数据库表进行操作: Mybatis是对SQL语句和java对象进行映射,仍需要开发人员编 ...