Effective JavaScript Item 27 使用闭包而不是字符串来封装代码
来源:互联网 发布:mate7电信没有4g 网络 编辑:程序博客网 时间:2024/06/15 06:47
本系列作为Effective JavaScript的读书笔记。
对于代码封装,在JavaScript中有两种方式可以办到。第一种就是使用function,第二种则是利用eval()函数,传入到该函数的字符串参数可以是一段代码。
当对使用哪种方式犹豫不决时,使用function。因为使用字符串的一个重要缺点是,传入的字符串并不是一个闭包,而function则可以代表一个闭包。关于闭包的特点,在Item 11中进行了描述。
下面是一段使用字符串来封装代码的例子:
function repeat(n, action) {for (var i = 0; i < n; i++) {eval(action);}}
传入到eval的action是一个字符串,用来代表需要被执行的逻辑,该字符串中出现的变量都会被解释成全局变量,在多数环境下,即window对象上的变量。
比如在下面的例子中:
var start = [], end = [], timings = [];repeat(1000, "start.push(Date.now()); f(); end.push(Date.now())");for (var i = 0, n = start.length; i < n; i++) {timings[i] = end[i] - start[i];}
repeat函数的第二个参数是一段代码,其中用到了两个变量start和end。
它们引用的是全局变量start和end。当上面的代码不在任何函数中时,还能够正常工作,如果将它们放到了函数中:
function benchmark() {var start = [], end = [], timings = [];repeat(1000, "start.push(Date.now()); f(); end.push(Date.now())");for (var i = 0, n = start.length; i < n; i++) {timings[i] = end[i] - start[i];}return timings;}
此时的start和end变量仍然引用的是全局变量start和end。如果在运行时没有这两个全局变量的任意一个,就会报出ReferenceError异常,这还是最好的结果。如果不凑巧在全局对象中拥有这两个同名的属性,那么程序的运行结果就不可预测了。
更好的封装代码的方式是使用function:
function repeat(n, action) {for (var i = 0; i < n; i++) {action();}}
此时,可以将上面的函数应用在任何函数的内部:
function benchmark() {var start = [], end = [], timings = [];repeat(1000, function() {start.push(Date.now());f();end.push(Date.now());});for (var i = 0, n = start.length; i < n; i++) {timings[i] = end[i] - start[i];}return timings;}
start和end能够引用到benchmark函数内部定义的start和end数组。这得益于闭包的性质。
另外一个不使用eval的原因是:在JavaScript的执行引擎中,对于以字符串形式封装的代码往往很难优化。因为字符串也许是动态生成的,编译器/解释器无法在执行前得知它的具体信息,就无法对它们进行优化。
总结:
- 如果确实需要使用字符串来封装一段代码时,确保在其中不要依赖任何非全局变量
- 优先使用闭包进行代码封装而不是使用字符串。
- Effective JavaScript Item 27 使用闭包而不是字符串来封装代码
- Effective JavaScript Item 46 优先使用数组而不是Object类型来表示有顺序的集合
- Effective JavaScript Item 31 优先使用Object.getPrototypeOf,而不是__proto__
- Effective JavaScript Item 11 掌握闭包
- Effective JavaScript Item 49 对于数组遍历,优先使用for循环,而不是for..in循环
- Effective JavaScript Item 13 使用即时调用的函数表达式(IIFE)来创建局部域
- Effective JavaScript Item 20 使用call方法来绑定this变量
- Effective JavaScript Item 22 使用arguments来创建接受可变参数列表的函数
- Effective JavaScript Item 24 使用一个变量来保存arguments的引用
- Effective JavaScript Item 26 使用bind来进行函数的柯里化(Curry)
- Effective JavaScript Item 10 避免使用with
- 《Effective C# 》Item 24: 使用元数据来控制程序
- Effective JavaScript Item 35 使用闭包来保存私有数据
- 尽量使用new/delete操作符,而不是malloc/free来分配内存-------Effective C++学习笔记
- Effective Modern C++: Item 13 -> 优先选择const_iterators而不是iterators
- JavaScript闭包封装,继承
- 《Effective STL》读书笔记二:Item 3(让容器中对象高效和正确地复制) Item 4(使用empty()而不是检查size())
- 《Effective C#》Item 4:使用Conditional属性来代替IF/ENDIF程序块
- 国密SM4对称算法实现说明(原SMS4无线局域网算法标准)
- 不出100年,地球你将认不出(科技闹的)
- 10个对开发项目有害的编程习惯
- PMC为超大规模部署提供高性价比定制化服务器硬件
- python sqlserver 完整的例子
- Effective JavaScript Item 27 使用闭包而不是字符串来封装代码
- ORACLE外连接小结(转载自wh62592855博客)
- 2.6内核增加usb支持 - 配置简介
- 笔记-ARX实体遍历DXF方法
- linux开发使用时的一些小技巧集锦
- android RotateAnimation使用
- 关于JDK
- 国密算法(SM2,SM3,SM4)完善与算法辅助工具开发
- C++库和C库的区别