JS篇——闭包

本文深入讲解JavaScript中的闭包概念,探讨闭包的作用及优势,并通过实例解析闭包的创建方式和潜在问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

千呼万唤始出来,我终于来总结javascript(以下都简称js)闭包了。闭包在js中有多重要呢?——很重要。话不多说,开撸。

为什么要用闭包

闭包作为我们js中必不可少的部分,我们究竟是为什么要使用它呢,这里从两个方面来说,什么是闭包和使用闭包的优势。

什么是闭包

闭包就是能够读取其他函数内部变量的函数。js中,由于js作用域的问题,内部函数可以读取外部函数里的变量,但是外部函数不可以读取内部函数的变量,闭包就是为了将函数内部和函数外部联系起来。

闭包的优势

1,一个变量长期驻扎在内存中(一不小心会成为缺点,占内存)。

2,避免全局变量的污染,加强封装性,达到对变量的保护作用。

3,私有成员的存在,有些方法和属性不想让外部修改,就可以使用闭包只提供方法获取。

js的垃圾回收机制

正式讲闭包的使用之前,先理解下js的垃圾回收机制。js有自动垃圾回收机制(Garbage Collecation简称GC),GC在回收内存的时候,会判断该变量是否被其他对象引用,在确定没有其他对象引用就会释放其占有的内存。使用闭包后,函数a被b引用,b又被a外的c引用(闭包特点一个函数嵌套一个函数),所以函数a在返回后不会被GC回收,因为在js垃圾回收机制中,如果两个对象互相引用,不再被第三者引用时,这两个互相引用的对象才会被回收。

如何创建闭包

  闭包的代码特点:

1,函数b嵌套在函数a内部。

2,函数a返回函数b。

先看个例子

function a(){
var i=0;
alert(++i);
}
//alert(i);//报异常,i is not defined
a();//1
a();//1

alert(i);//函数外部是无法访问函数内部的值的,所以会报异常,接下来两个函数a执行都弹出1,很简单的函数,就不用说了。

function a(){
var i=0;
function b(){
alert(++i);
 }
return b;
}
var c = a();
c();//1
c();//2
上面就创建了一个标准的闭包,在函数a中定义了函数b又return了函数b。
var c = a();//执行了a函数,返回函数a的返回值即函数b

c();//执行函数b,i变量自加1,最后弹出1

c();//再执行函数b,弹出2,上面执行两次都弹出1,这里却弹出了2,这说明i的变量一直在内存中保存并没有被回收,这就是闭包。

再举一个例子

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
  </ul>
</body>
<script>
function getLiIndex(){
    var li = document.getElementsByTagName('li');
    for(var i = 0;i<li.length;i++){
      li[i].onclick = function(){
        alert(i);//全部为5
      };
    }
  }
  getLiIndex();
</script>
</html>
上面是一个获取li索引值的一个功能,在这个例子中,在页面中点击li的时候,全部弹出5,这里因为这里闭包并不是记录的变量的值,只是记录的变量的一个引用,它是最后点击的时候才去获取i的值,所以它最后弹出的都为5.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
 <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
  </ul>
</body>
<script>
function getLiIndex(){
    var li = document.getElementsByTagName('li');
    for(var i = 0;i<li.length;i++){
      li[i].onclick = (function(j){
        return function(){
          alert(j);
        };
      })(i);
    }
  }
  getLiIndex();
</script>
</html>

  将这个例子改成如上的闭包,就可以解决全部弹出5这个问题了,这是因为将上面的函数改成了一个立即执行函数,并且捕捉当前的索引值,所以在点击li的时候,当前的li就弹出已经保存好的索引值。

闭包的缺点

1,由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除,即将变量值设为null。

2,闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。


好像还有很多没总结,逻辑还有点乱,貌似我应该重新再总结一遍,不管了,今天就这样了,下雨任性~~~~(>_<)~~~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值