[读书笔记]JavaScript 闭包(Closures)

1. 什么是闭包?

参考MDN

2. 闭包的使用示例

2.1 示例1

 1     <div>1</div>
 2     <div>2</div>
 3     <div>3</div>
 4     <script>
 5         var nodes = document.getElementsByTagName('div');
 6         for (var i = 0, len = nodes.length; i < len; i++) {
 7             /* 注意这里 */ 
 8             (function (i) {
 9 
10                 nodes[i].onclick = function () {
11                     console.log(i + 1);
12                 };
13 
14             })(i);
15 
16         };
17     </script>

2.2 延伸

1 var Type = {};
2 for (var i = 0, type; type = ['Number', 'String', 'Boolean', 'Array', 'Function',
3     'RegExp', 'Date', 'Undefined', 'Null','Error'][i++];) {
4     (function (type) {
5         Type['is' + type] = function (obj) {
6             return Object.prototype.toString.call(obj) === '[object ' + type + ']';
7         }
8     })(type);
9 };

说明:对于本例来说仅能判断类型,并不能保证类型的合法性,如判断Date如下所示:

1 function isValidDate(d) {
2     if (Object.prototype.toString.call(d) !== "[object Date]") {
3         return false;
4     }
5     return !isNaN(d.getTime());
6 }

3. 闭包的更多作用及示例

3.1 封装变量

在闭包块中实现“私有变量”

 1 var mult = (function () {
 2     var cache = {}, // “制表法”缓存结果集,避免重复的运算
 3         // 封闭calculate 函数
 4         calculate = function () { 
 5         var a = 1;
 6         for (var i = 0, l = arguments.length; i < l; i++) {
 7             a = a * arguments[i];
 8         }
 9 
10         return a;
11     };
12 
13     return function () {
14         var args = Array.prototype.join.call(arguments, ',');
15         if (args in cache) {
16             return cache[args];
17         }
18 
19         return cache[args] = calculate.apply(null, arguments);
20     };
21 })();

 MDN的例子用闭包模拟私有方法,也是模块模式的基础。

3.2 延续局部变量的寿命

1 var report = function( src ){
2 var img = new Image();
3 img.src = src;
4 };
5 report( 'www.xxx.com/stat' );
有问题的代码

为了解决函数局部变量在函数执行后立即被销毁的问题,可以用闭包来保存对局部变量的引用以达到延续局部变量生命周期。

 1 var report = (function () {
 2     var imgs = [];
 3 
 4     return function (src) {
 5         var img = new Image();
 6         imgs.push(img);
 7         img.src = src;
 8     }
 9 })();
10 
11 report('www.xxx.com/stat');

3.3 闭包和面向对象设计

 1  // 闭包写法
 2  var extent = function () {
 3      var value = 0;
 4      return {
 5          call: function () {
 6              value++;
 7              console.log(value);
 8          }
 9      };
10  };
11  var extent1 = extent(),
12      extent2 = extent();
13  extent1.call(); // 输出:1
14  extent1.call(); // 输出:2
15  extent1.call(); // 输出:3
16 
17  extent2.call(); // 输出:1
18 
19  var Extent = function () {
20      this.value = 0;
21  };
22 
23  // 面向对象的写法 
24  Extent.prototype.call = function () {
25      this.value++;
26      console.info(this.value);
27  };
28  var myExtent1 = new Extent();
29  myExtent1.call();
30  myExtent1.call();
31  myExtent1.call();
32 
33  var myExtent2 = new Extent();
34  myExtent2.call();

说明:本文代码来自《JavaScript设计模式与开发实践》和网络。

posted @ 2016-04-24 16:39  January  阅读(308)  评论(0编辑  收藏  举报