文章参照 http://www.jb51.net/article/28611.htm
一、值传递闭包
function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); } } var bar = foo(2); // bar 现在是一个闭包 bar(10);//16 bar(10);//17
代码说明:
运行完foo(2)方法之后,返回的是一个匿名方法,该方法被bar缓存起来了,即:
bar = function(y){ alert(x + y + (++tmp)); }
或者是
function bar(y){ alert(x + y + (++tmp)); }
其中x=2;tmp=3
1、因为bar实际上是全局window对象的值,即window.bar,因此bar不会被垃圾回收机制回收。
2、由于bar方法为foo()方法的内部方法,因此foo()方法也不会被垃圾回收机制回收,因此tmp的值不会被垃圾回收机制回收。
3、第一次运行bar(10)的时候tmp为3,第二次运行bar(10)的时候,tmp与第一次运行bar(10)的值是同一个,因此第二次运行bar(10)的值实际上是第一次tmp++之后的值为4
二、引用传递闭包
function foo(x) { var tmp = 3; return function (y) { alert(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; alert(x.memb); } } var age = new Number(2); var bar = foo(age); // bar 现在是一个引用了age的闭包 bar(10); bar(10);
代码说明:
1、age 是一个Number对象,可以简单的理解为一个json或者function对象,而不是一个数字
2、2.1因为bar实际上是全局window对象的值,即window.bar,因此bar不会被垃圾回收机制回收。
2.2bar方法为foo()方法的内部方法,因此foo()方法也不会被垃圾回收机制回收,因此tmp的值不会被垃圾回收机制回收。
bar 代表的是一个方法,即
function bar(y){ alert(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; alert(x.memb); }
或者
bar = function(y){ alert(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; alert(x.memb); }
其中,x为Number(2)对象,tmp的值为3
3、第一次运行bar(10)时,x.memb为undefined,x.memb = x.memb ? x.memb + 1 : 1;所以x.memb=1;
4、第二次运行bar(10)时,x对象还是之前的Number(2)对象,与第一次运行bar(10)的对象是同一个,但是,这次已经添加了一个属性x.memb=1;因此,x.memb = x.memb ? x.memb + 1 : 1;实际为x.memb = x.memb + 1;
个人理解——闭包:
1、定义一个方法foo,方法内部使用var定义变量,外部方法无法访问
2、执行完定义的方法foo之后要返回一个方法或者对象(属于window),这样就不会被垃圾回收机制回收
三、写插件的模板
var db = (function() { // 创建一个隐藏的object, 这个object持有一些数据 // 从外部是不能访问这个object的 var data = {}; // 创建一个函数, 这个函数提供一些访问data的数据的方法 return function(key, val) { if (val === undefined) { return data[key] } // get else { return data[key] = val } // set } // 我们可以调用这个匿名方法 // 返回这个内部函数,它是一个闭包 })(); db('x'); // 返回 undefined db('x', 1); // 设置data['x']为1 db('x'); // 返回 1 // 我们不可能访问data这个object本身 // 但是我们可以设置它的成员