JavaScript中的eval()函数详解


Posted in Javascript onAugust 22, 2013

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()时,它总是在调用它的上下文作用域内执行。其他的间接调用则使用全局对象作为其上下文作用域,并且无法读、写、定义局部变量和函数。下面有一段示例代码:

var geval=eval;                //使用别名调用evla将是全局eval
var x="global",y="global";    //两个全局变量
function f(){                //函数内执行的是局部eval
    var x="local";            //定义局部变量
    eval("x += ' chenged';");//直接使用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 global changed”

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

四、严格eval()

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

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

宝剑锋从磨砺出,梅花香自苦寒来。

Javascript 相关文章推荐
jquery validator 插件增加日期比较方法
Feb 21 Javascript
jquery调用wcf并展示出数据的方法
Jul 07 Javascript
js获取客户端操作系统类型的方法【测试可用】
May 27 Javascript
Javascript动画效果(3)
Oct 11 Javascript
微信小程序 网络API 上传、下载详解
Nov 09 Javascript
浅谈$_FILES数组为空的原因
Feb 16 Javascript
Chrome调试折腾记之JS断点调试技巧
Sep 11 Javascript
在angularJs中进行数据遍历的2种方法
Oct 08 Javascript
ES6 系列之 Generator 的自动执行的方法示例
Oct 19 Javascript
Vue路由前后端设计总结
Aug 06 Javascript
Node.js之删除文件夹(含递归删除)代码实例
Sep 09 Javascript
vue中keep-alive内置组件缓存的实例代码
Apr 16 Javascript
from 表单提交返回值用post或者是get方法实现
Aug 21 #Javascript
jquery重新播放css动画所遇问题解决
Aug 21 #Javascript
JS性能优化笔记搜索整理
Aug 21 #Javascript
JS检测图片大小的实例
Aug 21 #Javascript
html5的自定义data-*属性和jquery的data()方法的使用示例
Aug 21 #Javascript
JavaScript 中的日期和时间及表示标准介绍
Aug 21 #Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战二)
Aug 21 #Javascript
You might like
用PHP读取IMAP邮件
2006/10/09 PHP
PHP目录操作实例总结
2016/09/27 PHP
php 下 html5 XHR2 + FormData + File API 上传文件操作实例分析
2020/02/28 PHP
学习JS面向对象成果 借国庆发布个最新作品与大家交流
2009/10/03 Javascript
Javascript 页面模板化很多人没有使用过的方法
2012/06/05 Javascript
js showModalDialog弹出窗口实例详解
2014/01/07 Javascript
javascript消除window.close()的提示窗口
2015/05/20 Javascript
js获取滚动距离的方法
2015/05/30 Javascript
移动Web中图片自适应的两种JavaScript解决方法
2015/06/18 Javascript
基于Jquery和html5实现炫酷的3D焦点图动画
2016/03/02 Javascript
jQuery制作圣诞主题页面 更像是爱情影集
2016/08/10 Javascript
JavaScript里 ==与===区别详解
2016/08/16 Javascript
jQuery禁用快捷键例如禁用F5刷新 禁用右键菜单等的简单实现
2016/08/31 Javascript
AngularJS使用ocLazyLoad实现js延迟加载
2017/07/05 Javascript
vue使用Element组件时v-for循环里的表单项验证方法
2018/06/28 Javascript
一文搞懂ES6中的Map和Set
2019/05/20 Javascript
详解Python编程中包的概念与管理
2015/10/16 Python
Django发送邮件和itsdangerous模块的配合使用解析
2019/08/10 Python
Python GUI编程学习笔记之tkinter事件绑定操作详解
2020/03/30 Python
Python 分布式缓存之Reids数据类型操作详解
2020/06/24 Python
浅析python 字典嵌套
2020/09/29 Python
python实现在列表中查找某个元素的下标示例
2020/11/16 Python
python装饰器代码深入讲解
2021/03/01 Python
css3的transition效果和transfor效果示例介绍
2013/10/30 HTML / CSS
CSS3,线性渐变(linear-gradient)的使用总结
2017/01/09 HTML / CSS
L*SPACE官网:比基尼、泳装和度假服装
2019/03/18 全球购物
北京泡泡网网络有限公司.net面试题
2012/07/17 面试题
出口公司经理求职简历中的自我评价
2013/10/13 职场文书
求职信模板怎么做
2014/01/26 职场文书
学习经验演讲稿
2014/05/10 职场文书
五四青年节演讲稿
2014/05/26 职场文书
怎样写辞职信
2015/02/27 职场文书
倡议书范文大全
2015/04/28 职场文书
2015年小学体育工作总结
2015/05/22 职场文书
湘江北去观后感
2015/06/15 职场文书
Python字符串格式化方式
2022/04/07 Python