1.eval的初体验

eval这个语句,怎么说呢?十分好用,其实换句话说“用来装逼真是挺不错的。”

它接收一个字符串的实参,然后就可以像在解释器上输入对应字符串的内容那样执行该字符串。不信?看看这个// 我们可以用它定义一个函数> eval("function a(m) {return m + 1}")undefined> a(10)11// 注意如果是匿名函数要这样> a = eval("(function(m) {return m + 1})")

[Function]

> a(10)11// 进行算数运算> eval("1+2+3+4")10// 它还可以利用当前上下文> x = 12222221222222> eval("x")1222222

如果eval里面的值不是字符串的话则返回实参的值!!> eval(12)12// 计算是字符串对象也不行> eval(new String("console"))

[String: 'console']

这看起来确实很牛逼。有许多动态语言如Python, Ruby都有这个函数。不过我也很少在代码里见到它的身影。

这里传进去的字符串必须是符合语义的,不然的话会报语法错误。

对于这个方法的使用一直都有争议。我看到的下面两种说法。

1. 安全性考虑

eval比较危险。想想这样一种情形,如果我们不小心把eval接口开放了一部分出去。其实就相当于给我们的用户执行代码的权利。用户有意或是无意地让我们eval一些不符合语法规则的字符串内容,有可能会让我们的系统抛出异常。

2.优化不足

现代的JS解释器对大部分JS语法解析都进行了优化,而对那些调用了eval()的函数优化得并不是很多。

其实大多数情况下我们完全可以不必选择eval。目前来讲有很多的可替代方案。Don't use eval needlessly!

这里我举个例子。

有的时候我们可能想通过迭代来访问一个对象的各种属性,而事先我们不知道对象的属性有哪些是需要的,因此没办法把属性硬编到代码里面。var dict = {x: 1, y: 2}// 获取需要访问的键function getKey() {return 'x'}var key = getKey();console.log(eval("dict." + key));

我们如果事先不知道我们要访问的键为 'x'我们可能会写出上面的代码。其实可以用下面的代码来代替。虽然逼格相对没那么高,但是我觉得这样表达更为清晰。var dict = {x: 1, y: 2}// 获取需要访问的键function getKey() {return 'x'}var key = getKey();console.log(dict[key]);除非不得已否则最好还是不要用eval

因为你还有可能还会写出这样的代码。下面这个是我从资料中拿到的。比较有代表性:function boo(a) {    eval(a)

};

boo("return;");

这句代码看似没问题,其实它会报这个错误SyntaxError: Illegal return statement

这是为什么呢?因为eval实际参数的字符串执行时的上下文和调用eval函数的上下文环境是一样的,这使得eval("return;")被理解成单独的语句,而不是放在另一个函数里面执行的语句。(这可能有点难理解)。而return;如果不放在函数里面就没有任何意义了。所以直接报语法错误。

还不能理解?

在看我举个例子,我稍微改变一下原来的脚本function boo(a) {    var a = "console.log('mj')";    eval(a)

};

boo("return;");

这个时候函数就会打印出mj,由于我们赋予变量a另外一个值。而这个字符串"console.log('mg')"执行的上下文,其实就是在boo函数里面。而当a = "return;"的时候我们可以把解释器看成在一个普通的上下文作用域上面单独执行return;语句而没有关注它是否在一个函数里面。然而这是不符合语义的。

下面再来看一个比较过瘾的例子var x = "global";// 我在node上跑这里需要设置成全局变量才行不能加vary = "global";var geval = eval;// 函数f中eval执行字符串的上下文跟调用它的上下文作用域是相同的function f() {    var x = "local";    eval("x += 'changed';");    return x;

}// 函数g中geval执行的上下文是全局对象作为其上下文变量function g() {    var y = "local";

geval("y += 'changed';");    return y;

}console.log(f(), x);console.log(g(), y);

最后运行的结果是localchanged global

globalchanged local

表明了f函数是对函数内部x变量进行了拼接,而g函数却对全局变量y进行了拼接。所以这两个函数调用eval的上下文是不一样的。

2.eval的严格模式

这里也稍微提一下Javascript的严格模式。如果在脚本中开启严格模式(现在很多地方都是这样干的,可以帮助我们写出更加严谨的Javascript代码。)

在正常模式下eval的语法还是相对比较宽松的。

而在严格模式下,主要有这两点限制。不能在局部作用域中定义新的变量和函数。但是我们可以修改原来局部变量的值。

严格模式中eval被认为是保留字。我们不能用别的函数覆盖掉原来的eval函数。不然真的就乱套了。

还是简单举例说明:function a() {    var x = 2;    eval("var y = 1");    eval("var x = 12");    console.log(x);    console.log(y);

}

a();

这里打印的结果我们应该都能想到 12和 1;

我们在严格模式下试试这个脚本。原则上我们只要在脚本的最开始加上'use strict';就能够开启严格模式。'use strict';function a() {    var x = 2;    eval("var y = 1");    eval("var x = 12");    console.log(x);    console.log(y);

}

a();

这个时候在node下再运行脚本就会报错了。ReferenceError: y is not defined

这里我们用eval创建局部变量y失败了,但是我们可以修改已有的局部变量x。

啊,绕得好累,还有最后一个例子很简单,我们试着在严格模式下覆盖eval的值。'use strict'eval = function() {};

解释器直接报错SyntaxError: Unexpected eval or arguments in strict mode

我们不能在严格模式下做这种事情。严格模式有助于我们写出解释器比较认可的代码, 或者我们可以理解为Javascript的未来。有些东西它会直接用报错来提醒我们。比如当我们想通过delete来删除局部变量的时候,之前说过它会直接返回结果false,但是如果在严格模式下,这种行为解释器会直接抛出异常。有些大牛还是建议我们写脚本的时候尽可能用严格模式来写,有助于我们写出专业点的Javascript代码,也有助于日后的维护升级。

Happy Coding!!

作者:lanzhiheng

链接:https://www.jianshu.com/p/853d4f68541f

eval语法报错 ie10_JavaScript中eval语句浅尝相关推荐

  1. python双引号报错_Python中select语句中的双引号”“怎么处理

    我把MySQL的语句中放在了Python中(我用的Pycharm),有个sql语句是如下:insertinto`level-1metric`(`Year`,`SupplyChain`,`Region` ...

  2. eval语法报错 ie10_js eval 语法错误 急急急

    functionshowUserInfoList(responseText,statusText,xhr,form){varhtml='';varobj=eval("("+resp ...

  3. eval语法报错 ie10_IE10报如此错误如何解决?

    $(function(){ setTimeout(function(){ uploadify({ debug:false, text:'上传附件', auto:true, hide:false, si ...

  4. 解决idea的html代码中使用es6语法报错的问题

    解决idea的html代码中使用es6语法报错的问题 参考文章: (1)解决idea的html代码中使用es6语法报错的问题 (2)https://www.cnblogs.com/mayiaction ...

  5. .vue文件在webstorm中es6语法报错解决方法

    .vue文件在webstorm中es6语法报错解决方法 参考文章: (1).vue文件在webstorm中es6语法报错解决方法 (2)https://www.cnblogs.com/yuqing6/ ...

  6. mysql语句delete报错_「delete语句」MySQL——DELETE语句中的坑 - seo实验室

    delete语句 在网上搜索了一个mysql数据库删除重复数据的sql,原文是这样的: DELETE FROM people WHERE peopleName IN ( SELECT peopleNa ...

  7. 处理项目中的ESlint语法报错问题

    处理项目中的ESlint语法报错问题 1.在项目根目录下创建一个格式化文件时候的配置项.prettierrc文件 {"semi";false,"singleQuote&q ...

  8. 01-路由跳转 安装less this.$router.replace(path) 解决vue/cli3.0语法报错问题

    01-路由跳转 安装less this.$router.replace(path) 解决vue/cli3.0语法报错问题 参考文章: (1)01-路由跳转 安装less this.$router.re ...

  9. 已解决(Python语法报错)SyntaxError: invalid syntax

    已解决(Python语法报错)SyntaxError: invalid syntax 文章目录 报错信息 报错翻译 报错原因 解决方法 千人全栈VIP答疑群联系博主帮忙解决报错 报错信息 粉丝群里面一 ...

最新文章

  1. 常用基础参数SurvivorRatio讲解 || NewRatio讲解 || MaxTenuringThreshold讲解
  2. .NET 程序集单元测试工具 SmokeTest 应用指南
  3. php7.2.4 myspl5.7.21,linuapache php mysqlx下php开发环境搭建 Apache2 4 PHP7 1 MySQL5 7
  4. Quora使用到的技术
  5. linux系统微内核,科普:微内核操作系统现状
  6. 多个蓝牙缺陷可使攻击者假冒合法设备
  7. 编写程序,输入一个N,返回角谷变换(达到1所需)的次数
  8. 微信表情图像代表什么意思_电表型号怎么选 型号字母都代表什么意思
  9. latex在行末出现百分号的作用
  10. 韩顺平 零基础30天学会Java 学习笔记
  11. 计算机上机考试的系统,计算机上机考试系统
  12. CVPR 2021 UniT: Multimodal Multitask Learning with a Unifified Transformer
  13. 猴子问题----约瑟夫环算法
  14. 正则表达式之身份证号码验证
  15. php 苹果内购支付
  16. android 图片字体涂鸦,Android 编辑图片 Canvas画图,涂鸦,马赛克等(一)
  17. 水火箭的工作原理(化学反应)//2021-2-24 从群众中来,到群众中去
  18. mysql 基础语法3
  19. springboot前后端分离,邮箱/手机验证号激活和登录,手机注册和激活
  20. 盘点业务流程的SAP操作调整

热门文章

  1. 【超全指南】Java 8 中使用 Optional 处理 null 对象
  2. 商家中心设计 多sku商品发布_商家后台怎么设计商品信息?
  3. redis学习-redis五大数据类型
  4. 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)
  5. Django的基础操作总结
  6. C++学习笔记(九)——引用
  7. linux 有趣的命令
  8. jQuery源码解读三选择器
  9. .view-content:overflow:hidden 大错误
  10. web页面制作-环游记(一)