对闭包的简单解释
全局变量生存周期是永久,局部变量生存周期随着函数的调用介绍而销毁。闭包就是 在函数中定义且成为该函数内部返回的函数的自由变量 的变量,该变量不会随着外部函数调用结束而销毁。 (注:不光是变量,函数内声明的函数也可以形成闭包)
当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包。
function foo(){
let a = 1;
return function sum(){
console.log(a);
return a++;
};
}
let test = foo(); //闭包的产生:在执行foo函数时将返回的函数赋值给了一个变量,让foo中变量a可供返回的函数使用而不被销毁。
test(); //1
test(); //2
test(); //3
// foo函数中的变量a在foo调用结束后依旧保存了下来,这就是闭包。
函数也可以成为闭包
let bibao = function(){
let a = 1;
function test(){
a++;
console.log('函数依旧可以形成闭包'+a);
};
return function(){
test();
}
}
let fun = bibao();
fun();//函数依旧可以形成闭包2
fun();//函数依旧可以形成闭包3
fun();//函数依旧可以形成闭包4
for循环闭包
for (var i=1; i<=5; i++) {
(function(j) {
setTimeout( function timer() {
console.log( j );
}, j*1000 );
})( i );
}
闭包的应用一 模块
function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3
模块中闭包形成分析:
首先,CoolModule() 只是一个函数,必须要通过调用它来创建一个模块实例。如果不执行外部函数,内部作用域和闭包都无法被创建。
其次,CoolModule() 返回一个用对象字面量语法 { key: value, ... } 来表示的对象。这个返回的对象中含有对内部函数而不是内部数据变量的引用。我们保持内部数据变量是隐藏且私有的状态。可以将这个对象类型的返回值看作本质上是模块的公共 API。
闭包的应用二 封装变量
闭包可以帮助把一些不需要暴露在全局的变量封装成“私有变量”。例如使用js实现栈、队列等数据结构,需要将内部是数组进行私有化封装。
var mult = (function(){
var cache = {};
return function(){
var args = Array.prototype.join.call( arguments, ',' );
if ( args in cache ){
return cache[ args ];
}
var a = 1;
for ( var i = 0, l = arguments.length; i < l; i++ ){
a = a * arguments[i];
}
return cache[ args ] = a;
}
})();
alert ( mult( 1,2,3 ) ); // 输出:6
alert ( mult( 1,2,3 ) ); // 输出:6
闭包的应用三 延续局部变量的寿命
img 对象经常用于进行数据上报,如下所示:
var report = function( src ){
var img = new Image();
img.src = src;
};
report( 'http://xxx.com/getUserInfo' );
但是通过查询后台的记录我们得知,因为一些低版本浏览器的实现存在 bug,在这些浏览器下使用 report 函数进行数据上报会丢失 30%左右的数据,也就是说,report 函数并不是每一次都成功发起了 HTTP 请求。丢失数据的原因是 img 是 report 函数中的局部变量,当 report 函数的调用结束后,img 局部变量随即被销毁,而此时或许还没来得及发出 HTTP 请求,所以此次请求就会丢失掉。现在我们把 img 变量用闭包封闭起来,便能解决请求丢失的问题
var report = (function(){
var imgs = [];
return function( src ){
var img = new Image();
imgs.push( img );
img.src = src;
}
})();