深入理解JavaScript闭包以及应用场景

一、什么是闭包?

  • 闭包就是一个函数,它处于另一个函数中,并且可以访问它的外部函数中的变量。
function fun(){
    var n=0;
    return function(){ //这就是一个闭包,它可以使用变量n
    	n++; 
    	console.log("n="+n);
    }
}
var f=fun();
 f();  //输出:n=1
 f(); //输出:n=2

二、闭包有什么作用?

  • 访问外部函数的变量。
  • 防止外部函数执行完之后,变量被销毁。
  • 加强封装性。

三、闭包的缺点?

  • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,很容易造成内存泄漏。

四、闭包的应用场景

1. 通过循环给页面上多个dom节点绑定事件,点击编号为几的节点则弹出它对应的编号
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>

如果不使用闭包:

for(var i = 0; i < list.length; i++) {
  list[i].addEventListener('click', function(){
      alert(i)
    }, true)
}

由于点击事件是异步触发的,当事件被触发时,for循环以及结束了,此时变量i的值已经是5!所以当点击事件顺着作用域链从内向外查找变量i时,找到的值总是5,所以无论点击哪一项都会弹出5。
下面用闭包改写:

var list = document.getElementsByTagName('li')
for(var i = 0; i < list.length; i++) {
  list[i].addEventListener('click', function(i){
    return function() {
      alert(i+1)
      console.log(i+1)
    }
  }(i), true)
}

改成闭包之后,每次循环的i值都被封闭起来,这样在函数执行时,会查找定义时的作用域链,这个作用域链里的i值是在每次循环中都被保留的,因此点击不同的li会alert出不同编号。

2. setTimeout

原生的setTimeout传递的第一个函数是不能带参数的:

setTimeout(fun(),1000);

因此,闭包就派上用场了:

function fun(num){
  var age = num;
  return function(){
       console.log(age);
  }
}

var getAge = fun(200);//传入需要的参数,得到函数(闭包)的引用
var age = setTimeout(getAge,1000);//正确输出
3. 使用闭包访问私有变量
function Fun(){
  var name = 'tom';
  
  this.getName = function (){
    return name;
  }
}

var fun = new Fun(); 
console.log(fun.name);//输出undefined,在外部无法直接访问name
console.log(fun.getName());//输出tom

最后,觉得一位大佬说的很好:

闭包这东西,举个不恰当的例子:就像Java里常说的设计模式。
很多人痴迷于各种设计模式,就想方设法硬是用到工作中,然后就觉得高大上了,而不管合适不合适。实际上,那些前人总结出来的设计模式,确实是精华,确实值得学习。但是不管合适不合适、需要不需要地直接拿来用是不对的。我们应该吸收里面的思想而不是形式,等你代码写多了,经验多了,就会不经意地用上,甚至自创出之前没有但是更适合你自己的模式。

闭包也一样,闭包只是个术语而已,我们应该去了解它形成的原理,它的形成背后的知识点,比如作用域链、变量解析、词法环境等等,从而真正理解为什么出现闭包这种现象。而不是觉得它高大就必须把它用到工作中。等你代码写多了,涉猎范围广了,自然会不知不觉用上它。真的,到那时候,很可能你代码里出现了闭包,但是你却没有意识到。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值