eval函数不仅仅是一个函数。大多数函数只访问定义它们所在的作用域,而不能访问除此之外的作用域(词法作用域)。
eval函数具有访问调用它时的整个作用域的能力。
编译器编写者首次设法优化js时,eval函数很难高效地调用任何一个函数,因为一旦调用的函数是eval函数,那么每个函数调用都需要确保在运行时整个作用域对eval函数是可访问的。
语言标准演化出辨别两种不同的调用eval的方法
第一种方式:函数调用涉及eval标识符,被认为是一种“直接”调用eval函数的方式。编译器需要确保被执行的程序具有完全访问调用者局部作用域的权限。
例如:

其它方式:其它调用eval函数的方式被叫做“间接”。
两种方式eval函数的参数是在全局作用域内进行求值。
例如:绑定eval函数到另一个变量名,通过该变量名调用函数会使代码失去对所有局部作用域的访问能力。

直接调用eval函数的确切的定义取决于ECMAScript标准相当特殊的规范语言。唯一能够产生直接调用eval函数的语法是可能被(许多的)括号包裹的名称为eval的变量。编写间接调用eval函数的一种简洁方式是使用表达式序列运算符(,)和一个明显毫无意义的数字字面量。

  1. (0,eval)(src);

这是如何工作的呢?
数字字面量0被求值但其值被直接忽略,括号表示的序列表达式产生的结果是eval函数。因此,(0,eval)的行为几乎与简单的eval函数标识符完全一致,一个重要的区别在于整个调用表达式被视为一种间接调用eval函数的方式。
直接调用eval函数的能力很容易被滥用。
对一个来自网络的源字符串进行求值,可能会暴露其内部细节给一些未受信者。
直接调用eval函数导致其包含的函数以及所有直到程序最外层的函数运行相当缓慢的风险。
除非有一个检查局部作用域的特别能力的明确需求,否则应当使用更不容易滥用、更廉价的间接调用eval函数的方式。

提示

  • 将eval函数同一个毫无意义的字面量包裹在序列表达式中以达到强制使用间接调用eval函数的目的

  • 尽可能间接调用eval函数,而不要直接调用eval函数。

[Effective JavaScript 笔记]第17条:间接调用eval函数优于直接调用的更多相关文章

  1. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  2. [Effective JavaScript 笔记]第38条:在子类的构造函数中调用父类的构造函数

    示例 场景类 场景图(scene)是在可视化的过程中(如游戏或图形仿真场景)描述一个场景的对象集合.一个简单的场景包含了在该场景中的所有对象(称角色),以及所有角色的预加载图像数据集,还包含一个底层图 ...

  3. [Effective JavaScript 笔记]第52条:数组字面量优于数组构造函数

    js的优雅很大程序要归功于程序中常见的构造块(Object,Function及Array)的简明的字面量语法.字面量是一种表示数组的优雅方法. var a=[1,2,3,5,7,8]; 也可以使用构造 ...

  4. [Effective JavaScript 笔记] 第14条:当心命名函数表达式笨拙的作用域

    js函数会根据上下文改变其含义. function double(x){return x*2;} 这是一个函数声明,也可以是一个命名函数表达式(named function expression),取 ...

  5. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  6. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  7. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  8. [Effective JavaScript 笔记]第16条:避免使用eval创建局部变量

    js中的eval函数是一个强大.灵活的工具.强大的工具容易被滥用,所以了解是值得的.(本人只用过它来处理json数据).错误使用eval函数的方式一:允许它干扰作用域.调用eval函数会将其参数作为j ...

  9. [Effective JavaScript 笔记]第67条:绝不要同步地调用异步的回调函数

    设想有downloadAsync函数的一种变种,它持有一个缓存(实现为一个Dict)来避免多次下载同一个文件.在文件已经被缓存的情况下,立即调用回调函数是最优选择. var cache=new Dic ...

随机推荐

  1. 程序员"青春饭"问题之我见

      程序员"青春饭"问题之我见 声明:转载请注明出处.http://www.cnblogs.com/hzg1981/ 1. 问题描述 问题1: 什么是程序员? 在本文中程序员的定义 ...

  2. 第二章 OO大原则

    昨天忙了一天,晚上加班到了12点,虽然工作有时候比较累,但是整体来讲还是比较轻松的,国企加上我是今年才毕业的应届生,导致了现在这种情况.工资也真的不算高...但我觉得最开始还是要踏踏实实一点比较好.学 ...

  3. WCF安装Windows服务

    安装图解: 安装命令: 1. 开始 ->运行 ->cmd2. cd到C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319(Framework版本号按I ...

  4. 使用Git进行代码管理心得

    关于使用Git for Windows来clone和上传项目 首先到Git for Windows的官网下载并安装 在本地用来保存clone文件的文件夹右键,选择Git Bash Here: 在打开的 ...

  5. JQuery学习(1)

    JQuery学前准备 JQuery的各种包: 1.jquery-ui(包含小工具及组件) 2.jquery-1.7.1.intellisense.js(智能提示包) 3.jquery-1.7.1.js ...

  6. Java基础-继承-子类与父类执行顺序

    代码 public class Test { public static void main(String[] args) { new Circle(); } } class Draw { publi ...

  7. 【POJ 1273】Drainage Ditches(网络流)

    一直不明白为什么我的耗时几百毫秒,明明差不多的程序啊,我改来改去还是几百毫秒....一个小时后:明白了,原来把最大值0x3f(77)取0x3f3f3f3f就把时间缩短为16ms了.可是为什么原来那样没 ...

  8. std::ios::sync_with_stdio(false);

    这句语句是用来取消cin的同步,什么叫同步呢?就是iostream的缓冲跟stdio的同步.如果你已经在头文件上用了using namespace std;那么就可以去掉前面的std::了.取消后就c ...

  9. 解决vs2015使用fopen、fprintf等函数报错的问题

    出现错误提示: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable ...

  10. org.springframework.beans.factory.annotation.Autowired(required=true)

    Injection of autowired dependencies failed ERROR org.springframework.web.context.ContextLoader  - Co ...