对js闭包的理解

首先的简单理解可以是:闭包=内层函数+引用的外层函数变量。(官方解释为:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域)用我自己的话来说就是:这是一个因为js作用域而引起的衍生物。因为大多数时候,我们只能通过从作用域靠里的地方去访问作用域靠外的地方 比如说全局变量在任何一个函数里都可以被访问到 。或者比如说当发生函数嵌套的时候 ,第二层里的函数可以访问外层函数作用域里的变量。而一般情况下, 我们无法从外层作用域访问到内层作用域中的变量,要是这是可以实行的话,那const let 这种块级作用域也就没有存在的必要了哈哈,反正哪里都能访问到。就是因为很多时候我们需要变量的一定程度的私有,不然所有变量都在全局作用域的时候也不安全,别人随便在一个地方改一下,那你的变量就变了。所以在这样的背景下,我们既要保护变量,使得它不会被随意更改。但是有时候我们又需要使用它。如果用模块化思想来看的话,我们创建一个函数就是一个功能,类似于小组件,那么我们有时候想要访问一个小组件内部变量也是很正常的事情。毕竟所有的东西都是为了处在全局中的主事件而生的,但是我们又访问不到。
就是相当于在作用域上我们只有一个从里往外直接访问的箭头,但是没有从外往里的箭头。那我们就想办法,想把它连起来嘛。我感觉闭包的做法其实就有点像,暴露个接口的感觉 。
就是比如我们现在想在全局作用域下去访问一个函数a里的变量x,我们选择在函数里再写一个函数b,然后函数b自然是可以访问到变量x的。这时候我们就是采用一种,比较迂回的方法啊,因为你直接拿,拿不到嘛。我们在函数a里,调用函数b。其实这时候就是形成闭包了。然后这里就有一个很多人可能一开始接触闭包这个概念,会有一种感觉就是认为闭包肯定是要有return的,但是其实闭包它和你re不return没有关系,它就是一个概念,在这里它就是函数b和变量x,在代码里你可以认为就是那段代码块。它就代表闭包 。只不过很多时候,我们确实需要拿到或者说在全局定义域里使用函数a里的变量x,所以我们就很曲线地,让函数a把函数b抛出来,就像一个接口。这说实话,我想起来vue里的那些组件啊,它们就是使用es6的模块化的关键字import 导入模块和export或者export default导出模块。这样的话,代码之间的耦合性就降低了。
然后关于闭包是否引起内存泄露的问题。js里关于内存泄露的定义就是在一段程序里,没有及时释放,不能再用到的内存就叫内存泄露。因为我们都知道,我们在跑一个项目啊,或者js文件的时候,我们写的代码都是在内存里跑的。对于持续运行的服务进程来说,如果没有及时释放不再使用的内存,就如果极端一点,你在代码里写一个while(true){
}让它去跑,显然,它会卡住,宏观一点来说是你页面暂时像“死机”了一样完全静态了,啥也干不了。就如果你的页面上本来有文字或者是gif图片的话,这时候会出现文字也选择不了,gif也动不了的情况。说得再细一点的话,这其实是你的event loop事件环一直在跑那个js语句,导致它一直在那个地方阻塞,没办法去做别的了,比如说浏览器的render渲染环节。然后这时候你的用户试着去选取文本,这涉及到点击,涉及到查看dom中的文本,这些现在事件环都不能去处理了。就是说现在在关闭浏览器之前,你的浏览器申请到的内存都被用去跑那个死循环了。那对于其他内存,或者说你要办的主线程中的“正事”来说,这就是一种内存泄露。
好了,现在话说回来。说完了内存泄露的定义,我们来看一下闭包中的内存泄露发生在哪里。其实很简单,就拿这段代码来说。

function a() {
  var x = 1;
  function b() {
    console.log(x);
  }
  return b;
}
const res = a();
res();

还要补充一点的是js的垃圾回收机制的原则,这个很简单,宗旨就是如果一个变量没有任何引用了,那么js的执行环境就会负责去把这个变量占用的内存释放掉。而一个全局变量,代码执行完是不销毁的,因为我们随时都可能会用到这个变量,所以不销毁,它的生命周期和整个程序的运行周期是一样的,就如果你一个js文件在node/浏览器里跑,只有你关掉浏览器窗口或者停止编译的时候它的内存才会释放出来。(ps:这也是为什么要少使用全局变量的一个原因,除了有被随意篡改的风险以外,它也是比较吃内存的)而这段代码中的res,显然是个全局变量,那么它引用的a()也就不会被销毁,然后a函数里面的变量又在b函数里被引用,那它就不会被销毁了。在这里就发生了内存泄露,因为一般情况下,普通函数中的变量的生命周期和函数的生命周期是一样的,函数执行完就被销毁,把内存释放出来。所以我们还是不要过度使用闭包。不然在一个程序里,它很吃内存

下面我为大家推荐几篇我之前了解这些的知识的文章或者视频链接:
事件原理事件循环
js作用域
内存泄露的概念

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值