闭包相关以及内存回收

本文介绍了JavaScript中的闭包概念,展示了如何通过闭包访问函数内部变量,并讨论了由此引发的内存消耗问题。经典示例解释了闭包在定时器和循环中的应用,以及如何防止内存泄漏。最后,探讨了JavaScript的垃圾回收机制,特别是标记清除策略,强调了合理使用闭包和管理内存的重要性。
摘要由CSDN通过智能技术生成

闭包

function f1() {
  var a = 1
  function f2() {
    return a
  }
  return f2 // return为了让f2函数能够被使用
}
var b = f1()
b() // 1    b作为全局变量获取到了局部变量a的值

在上方代码中,函数 f2 被包括在函数 f1 内部,这时 f1 内部的所有局部变量,对 f2 都是可见的。
既然 f2 可以读取 f1 中的局部变量,那么只要把 f2 作为返回值,就可以在 f1 外部读取它的内部变量了。

上面代码中的 f2 函数,就是闭包。(通俗理解:闭包就是能够读取其他函数内部变量的函数。)

闭包可以简单理解成 “定义在一个函数内部的函数“ 。所以,在本质上,闭包是连接函数内外部的桥梁。

经典例1

function f() {
  var a = 1 // 没有被闭包所引用,函数执行完毕被回收
  console.log(++a)
}
f() // 2
f() // 2  
// 变量a会在每次被调用时新创建
function f() {
  var a = 1 // 被闭包所引用,不会被回收
  return function () {
    var b = 0
    console.log(++a);
    console.log(++b)
  }
}
var f1 = f()
f1() // 2 1
f1() // 3 1

一般情况下,在函数 f 执行完后,就应该连同它里面的变量一同被销毁。
但是在这个例子中,匿名函数内部引用着 f 里的变量 a,所以变量 a 无法被销毁,而变量 b 是每次被调用时新创建的,所以每次 f1 执行完后它就把属于自己的变量(b)连同自己一起销毁,于是乎最后就剩下孤零零的 a,于是这里就产生了内存消耗的问题。

经典例2 定时器与闭包

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000)
} // 输出三次3

由于js是单线程的,所以在执行for循环的时候setTimeout被安排到任务队列中排队等待执行,等到setTimeout可以执行的时候,for循环已经结束,i的值也已经变为3,所以打印出来三个3。

解决办法:引入闭包来保存变量i,将setTimeout放入立即执行函数中,将for循环中的循环值i作为参数传递:

for (var i = 0; i < 3; i++) {
  (function (i) {
    setTimeout(() => {
      console.log(i);
    }, 1000)
  }(i))
} // (1s later)  0 1 2 

实现每隔1000毫秒分别依次输出数字:把时间1000改为1000*i

闭包的作用

  1. 可以在函数的外部访问到函数内部的变量,也就是「间接访问一个变量」。
  2. 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁。
  3. 防止命名冲突。

使用闭包可能会导致的问题「内存泄漏」:
内存泄露就是指用不到(访问不到)的变量,依然占据内存空间,不能被再次利用起来,增大了内存消耗,造成内存泄漏。
解决方法是可以在使用完变量后手动为它赋值为null。

有时会使用全局变量去存储临时信息,那么要记得使用完毕后手动赋值为 null,以回收内存。

常见的四种js内存泄漏

1.全局变量
有时候我们无法避免使用全局变量,那么记得在使用完毕后手动释放它们,例如让变量指向null。

2 被遗忘的定时器或回调函数
不需要时记得清除定时器、移除监听事件

3 闭包 (解决方法:使用完变量后手动为它赋值为null

内存回收

在js中,垃圾回收器每隔一段时间就会找出那些不再使用的数据,并释放其所占用的内存空间。

以全局变量和局部变量来说,函数中的局部变量在函数执行结束后不再被需要,所以垃圾回收器会识别并释放它们(闭包可以让这些变量保存在内存中,不会随着函数的结束而销毁)。
而对于全局变量,垃圾回收器很难判断这些变量是否需要,所以尽量少使用全局变量。

垃圾回收模式:标记清除
从根部(在js中,我们一般认定全局对象window作为root)出发看是否能达到某个对象,如果能达到则认定这个对象还被需要,如果无法达到,则释放它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲起来blingbling

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值