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 相关文章推荐
node.js中的fs.exists方法使用说明
Dec 17 Javascript
javascript中的五种基本数据类型
Aug 26 Javascript
js实现无限级树形导航列表效果代码
Sep 23 Javascript
微信支付如何实现内置浏览器的H5页面支付
Sep 25 Javascript
js实现密码强度检测【附示例】
Mar 30 Javascript
网页挂马方式整理及详细介绍
Nov 03 Javascript
JS实现鼠标移上去显示图片或微信二维码
Dec 14 Javascript
bootstrap+jQuery 实现下拉菜单中复选框全选和全不选效果
Jun 12 jQuery
JavaScript算法教程之sku(库存量单位)详解
Jun 29 Javascript
解决vue同一slot在组件中渲染多次的问题
Sep 06 Javascript
Vue-CLI 3 scp2自动部署项目至服务器的方法
Jul 24 Javascript
Ajax请求超时与网络异常处理图文详解
May 23 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 insert语法详解
2008/06/07 PHP
thinkPHP自动验证、自动添加及表单错误问题分析
2016/10/17 PHP
javascript学习网址备忘
2007/05/29 Javascript
jquery 弹出层注册页面等(asp.net后台)
2010/06/17 Javascript
基于jQuery的树控件实现代码(asp.net+json)
2010/07/11 Javascript
Jquery动态进行图片缩略的原理及实现
2013/08/13 Javascript
分享一则javascript 调试技巧
2015/01/02 Javascript
js实现文本框选中的方法
2015/05/26 Javascript
以JavaScript来实现WordPress中的二级导航菜单的方法
2015/12/14 Javascript
Vue.js 和 MVVM 的注意事项
2016/11/07 Javascript
原生javascript实现读写CSS样式的方法详解
2017/02/20 Javascript
JS实现自定义状态栏动画文字效果示例
2017/10/12 Javascript
Node.js API详解之 assert模块用法实例分析
2020/05/26 Javascript
微信小程序连续签到7天积分获得功能的示例代码
2020/08/20 Javascript
使用python开发vim插件及心得分享
2014/11/04 Python
python服务器与android客户端socket通信实例
2014/11/12 Python
Python爬取国外天气预报网站的方法
2015/07/10 Python
python开发之文件操作用法实例
2015/11/13 Python
python操作字典类型的常用方法(推荐)
2016/05/16 Python
python爬虫之百度API调用方法
2017/06/11 Python
Python3.6 + TensorFlow 安装配置图文教程(Windows 64 bit)
2020/02/24 Python
Python本地及虚拟解释器配置过程解析
2020/10/13 Python
灵活运用CSS3特性绘制简易版围棋效果
2016/09/28 HTML / CSS
使用HTML5的File实现base64和图片的互转
2013/08/01 HTML / CSS
德国高品质男装及配饰商城:Cultizm(Raw Denim原色牛仔裤)
2018/04/16 全球购物
印度排名第一的蛋糕、鲜花和礼品送货:Winni
2019/08/02 全球购物
Timberland澳大利亚官网:全球领先的户外品牌
2019/12/10 全球购物
英国在线定做百叶窗网站:Make My Blinds
2020/08/17 全球购物
《值日生》教学反思
2014/02/17 职场文书
幼儿园教师节演讲稿
2014/09/03 职场文书
交通安全温馨提示语
2015/07/14 职场文书
2016教师节问候语
2015/11/10 职场文书
2016年记者节感言
2015/12/08 职场文书
HTML5来实现本地文件读取和写入的实现方法
2021/05/25 HTML / CSS
mysql升级到5.7时,wordpress导数据报错1067的问题
2021/05/27 MySQL
vscode远程免密登入Linux服务器的配置方法
2022/06/28 Servers