本文收集了多本书里对
JavaScript闭包(Closure)
的解释,或许会对理解闭包有必定帮助。javascript
var fn = f(); // 将函数f 的返回值赋值给变量fn fn(); // 1 fn(); //2 fn(); //3 function f() { var cnt = 0; return function() { return ++cnt; } } var fn1 = f1(); fn1(); //1 fn1(); //1 function f1(){ var cnt = 0; return ++cnt; }
从表面上来看,闭包是一种具备状态的函数。或者也能够将闭包的特征理解为,其相关的局部变量在函数调用结束以后将会继续存在。html
经过实现信息隐藏java
//使用了闭包的模块 // 在此调用匿名函数 // 因为匿名函数的返回值是一个函数,因此变量sum 是一个函数 var sum = (function() { // 没法从函数外部访问该名称 // 实际上,这变成了一个私有变量 // 通常来讲,在函数被调用以后该名称就将没法再被访问 // 不过因为是在被返回的匿名函数中,因此仍能够继续被使用 var position = { x:2, y:3 }; // 一样是一个从函数外部没法被访问的私有变量 // 将其命名为sum 也能够。不过为了不混淆,这里采用其余名称 function sum_internal(a, b) { return Number(a) + Number(b); } // 只不过是为了使用上面的两个名称而随意设计的返回值 return function(a, b) { print('x = ', position.x); return sum_internal(a, b); }; } )(); // 调用 sum(3, 4); x = 2 7
在利用函数做用域能够封装名称,以及闭包可使名称在函数调用结束后依然存在这两个特性后,信息隐藏得以实现。编程
(function() { 函数体 })();
计数器功能的类设计模式
function counter_class(init) { // 初始值能够经过参数设定 var cnt = init || 0; // 设置默认参数的习惯作法(参见5.5 节) // 若有必要,可在此声明私有变量与私有函数 return { // 公有方法 show:function() { print(cnt); }, up:function() { cnt++; return this; }, // return this 在使用方法链时很方便 down:function() { cnt--; return this; } }; } // 使用代码 var counter1 = counter_class(); counter1.show(); 0 counter1.up(); counter1.show(); 1 var counter2 = counter_class(10); counter2.up().up().up().show(); // 方法链 13
表达式闭包闭包
JavaScript 有一种自带的加强功能,称为支持函数型程序设计的表达式闭包(Expression closure)。异步
var sum = function(a, b) { return Number(a) + Number(b); } //能够省略为 var sum = function(a, b) Number(a) + Number(b);
因为IE9以前的版本对JScript对象和COM对象使用不一样的垃圾收集例程,所以闭包在IE的这些版本中会致使一些特殊的问题。具体来讲,若是闭包的做用域链中保存着一个HTML元素,那么就意味着该元素将没法被销毁。函数
function assignHandler(){ var element = document.getElementById("someElement"); element.onclick = function(){ alert(element.id); }; } //把element变量设置为null。这样就可以解除对DOM对象的引用,顺利地减小其引用数,确保正常回收其占用的内存。 function assignHandler(){ var element = document.getElementById("someElement"); var id = element.id; element.onclick = function(){ alert(id); }; element = null; }
延续局部变量的寿命this
//把img变量用闭包封闭起来,便能解决请求丢失的问题 var report = (function(){ var imgs = []; return function( src ){ var img = new Image(); imgs.push( img ); img.src = src; } })();