js闭包原理和用法

对闭包的简单解释

全局变量生存周期是永久,局部变量生存周期随着函数的调用介绍而销毁。闭包就是 在函数中定义且成为该函数内部返回的函数的自由变量 的变量,该变量不会随着外部函数调用结束而销毁。 (注:不光是变量,函数内声明的函数也可以形成闭包)

当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包。

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; 
     } 
})(); 
原文地址:https://www.cnblogs.com/honkerzh/p/10572801.html