闭包的简单了解

闭包:(闭包找的是同一地址中父级函数中对应变量最终的值)

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

闭包特点
1.函数嵌套函数
2.内部函数引用外部函数的变量或者形参
3.被引用的变量或者形参可以常驻内存

function aaa(a){
  var b = 20;
  function bbb(){
    console.log(a,b);  //闭包
  }
  return bbb;
}
var ccc = aaa(10);
console.log("aaa函数执行完毕,被回收");
ccc();   //10,20

好处:
1.有一个变量常驻在内存当中
2.避免全局变量污染
3.通过外部无法访问到内部数据

var a = 2;  //全局变量被污染
function show(){
  a++;
  console.log(a);
}

show();  //3
show();  //4

function show(){
  var a = 2;
  a++;
  console.log(a);   
}

show();         //3
show();         //3 
console.log(a); //报错  a is not defined  因为垃圾回收机制 show()函数被回收了
 

既要保存之前调用结果,还要不污染全局变量。
让这个变量常驻内存,就是闭包。

function aaa(){
      var a = 2;   //被创建的一个局部变量
      function bbb(){  //函数中嵌套函数,所以这是个闭包
        a++;           //对父函数中的变量进行运算
        console.log(a);  
      }
      return bbb;
    }

 var ccc = aaa();
  ccc();    //3
  ccc();    //4
  console.log(a);   //a is not difined  因为闭包内的变量外部是无法访问的

aaa() 创建了一个局部变量 a 和一个名为 bbb() 的函数。bbb() 是定义在aaa() 里的内部函数,并且仅在 aaa() 函数体内可用。请注意,bbb() 没有自己的局部变量。然而,因为它可以访问到外部函数的变量,所以 bbb() 可以使用父函数 aaa() 中声明的变量 a ,又因为闭包的原因所以bbb()中a++后的值会被保存下来,最后通过return又返回给父函数,从而改变父函数中声明的局部变量,so最终的结果就是代码3,4

上述代码的立即执行函数写法:var ccc = (函数声明)(函数调用)

var ccc = (function(){
  var a = 2;
  return function(){
     a++;
     console.log(a);
  }
})();

ccc();   //3
ccc();   //4

弊端:
在IE浏览器下会引发内存泄漏

window.onload = function(){
     var div = document.getElementById("...")   
     div.onclick = function(){
      //在IE下的div这个变量中由于通过闭包调用,不会释放,所以会造成内存泄漏
         alert(div.id)
     } 
}

解决方法

window.onload = function(){
     var div = document.getElementById("...");
     var id = div.id;
     div.onclick = function(){
          alert(id);
     }
     //div 所占的内存就被释放掉了
       div = null;

【注】事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;利用闭包来进行模块化的开发;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率,同时避免对命名空间的污染,最重要的是可以从一个域中取出原本访问不到的变量去使用

利用闭包来进行模块化的开发:

弊端
无法进行二次开发
解决方法:
一:放大模式 【注】本地存储的时候会有加载顺序的问题,服务器上会有加载延迟的问题导致原本顺序错误
二:宽放大模式

var moduleA = (function (mod) {
        function showC() {
          console.log("我是showC");
        }
        mod.outC = showC;
        return mod;
      })(moduleA || {});  
 //如果先执行的这个,那么这个函数中开始的时候mod是没有值的,所以调用的是一个空对象,
 //接下来执行函数,最后返回一个mod值,以备待用

当上面的代码执行完毕后里面已经有值了,所以下面的代码可以直接调用moduleA方法,最终moduleA对外暴露时既有C的值也有A,B的值。同理如果这两个代码顺序颠倒,也不会影响最终输出的结果

   var moduleA = (function (mod) {
        var count = 10; //私有变量
        function showA() {
          //私有方法
          count++;
          console.log(count);
        }
        function showB() {
          count *= 10;
          console.log(count);
        }
        mod.outA = showA;
        mod.outB = showB;

        return mod;
      })(moduleA || {});

例子

例1

function fn(){
	var a = 3;
	return function(){
		return  ++a;                                     
	}
}
alert(fn()());  //4
alert(fn()());  //4    

例2

function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();  //Mozilla
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值