闭包真的还会造成内存泄露吗?你不知道的闭包与垃圾回收!

news/2024/7/19 15:02:45 标签: javascript, js, 函数闭包, 内存泄漏, 垃圾回收

文章目录

  • 前言
  • 一、闭包是什么?
  • 二、闭包有什么好处和坏处呢?
    • 1.好处
    • 2.坏处
  • 二、闭包会造成内存泄露吗?
    • 1.前言
    • 2.闭包会造成内存泄露吗,如果会为什么还会再react hooks中大量使用呢?
  • 三、为什么ie8及之前会造成内存泄露?
    • 1.为什么会造成内存泄露
    • 2.引用计数的缺陷
    • 3.为什么ie8及之前还会存在引用计数呢?
  • 总结


前言

相信大家在学习前端的路上都有接触到过闭包这个东西,并且这也是面试中的常客。那么闭包究竟是个什么呢?让我们一起来看看吧。

一、闭包是什么?

函数内部的变量不会影响到外部作用域,并且父函数返回的子函数可以访问到其父函数作用域的变量。

换句通俗的话说呢,就是一个作用域能访问另一个作用域的变量,且局部变量会常驻在内存中不会被回收。

二、闭包有什么好处和坏处呢?

1.好处

1.可以让外部函数访问内部变量。

2.能将局部变量存储在内存中达到重复使用。

3.可以避免使用全局变量造成全局污染。

2.坏处

会造成内存泄露(此处并不是绝对的,下面我将详细探讨闭包的内存泄露问题)

二、闭包会造成内存泄露吗?

1.前言

之前因为自己没有去实践过,所以看到网上说闭包会造成内存泄露,也就这么认为了。

在我学习了react hooks之后,我发现hook里面的useState就是利用闭包来实现每次渲染保持变量不变的,当时我就在想,如果闭包会造成内存泄露,那么react hooks里面不就会使用大量的闭包吗?这样的话性能也太差了吧?带着疑问,我查阅了书籍还有资料,发现了这个问题。

2.闭包会造成内存泄露吗,如果会为什么还会再react hooks中大量使用呢?

首先,闭包会造成内存泄露!!!但是只在ie8及之前会造成内存泄露。
现在的闭包已经不会造成内存泄露了。

三、为什么ie8及之前会造成内存泄露?

如果要探讨内存泄露这个问题,首先我们得先搞清楚,为什么会造成内存泄漏

1.为什么会造成内存泄露

这一点得从垃圾回收机制说起,感兴趣的朋友可以去看我的另一篇专门讲垃圾回收机制的博客。
带你探索垃圾回收

首先,我们知道现在最常用的垃圾回收策略是标记清除,但在最早的时候,我们是使用引用计数来作为我们的垃圾回收策略的,但因为引用计数存在一些问题,所以被弃用了,但是,内存泄漏就是由引用计数造成的!!!!

2.引用计数的缺陷

引用计数的大概思路就是给声明变量赋给一个引用值,如果值被赋给另一个变量就+1,如果被覆盖就-1,当引用数为0时,就会释放这个值的内存。

引用计数存在了一个很严重的问题,循环引用。
循环引用的意思就是对象A有一个指针指向对象B,而对象B也引用了对象A,比如:

javascript">	function problem() {
        let objA = new Object()
        let objB = new Object()

        ObjA.test1 = objB
        objB.test2 = objA
      }

这个例子中,objA和objB通过各自的属性相互引用,导致引用数都是2.,在引用计数下,他们引用数永远不会到达0,如果函数被多次调用,则会导致大量内存永远不会被释放,从而造成内存泄露!

3.为什么ie8及之前还会存在引用计数呢?

在ie8及更早的版本中,并非所有对象都是原生js对象。BOM和DOM中的对象是C++实现的组件对象模型对象,简称COM对象。

COM对象是使用引用计数实现垃圾回收的,所以,即使这些版本的ie已经使用标记清除,但js存取的COM对象依旧是使用引用计数的。所以只要涉及到了COM对象,那么就会遇到循环引用的问题,比如:

javascript">	let box = document.querySelector('.box')
    let obj = new Object()
    obj.box = box
    box.obj = obj

在这个例子里,DOM对象和原生js对象之间造成了循环引用,所以DOM元素的内存永远不会被清除。从而造成内存泄漏

总结

在ie9之后已经全面改成了js对象啦,这避免了由于存在两套垃圾回收算法而导致的问题,还解决了内存泄露现象!

现在我们可以愉快的使用闭包啦!


http://www.niftyadmin.cn/n/861662.html

相关文章

【JS垃圾回收】带你探索垃圾回收机制和Chrome V8垃圾回收机制

文章目录前言一、什么是垃圾回收?1.基本思路2.为什么要进行垃圾回收二、怎样进行垃圾回收1.标记清除优点缺点2.引用计数优点缺点三、Chrome V8垃圾回收机制1.为什么需要优化垃圾回收算法2.基本概念3.新生代垃圾回收器 - Scavenge4.老生代垃圾回收 - Mark-Sweep &…

深入透析Promise几种方法(含手撕思路讲解及坑点)

文章目录前言一、Promise.all()1.介绍2.实例状态全为fulfilled状态有一个为rejected3.代码实现思路代码二、Promise.race()1.介绍2.实例3.代码实现思路代码总结前言 前面我们简单实现了一个promise,不懂的同学,传送门:深入透析Promise 那么…

【Diff算法图解】带你探索React、Vue2.x的Diff算法

文章目录前言一、Virtual DOM(虚拟dom)二、React Diff实现思想移动节点增加节点移除节点React Diff的缺陷三、Vue2.X Diff实现思想移动节点特殊情况增加节点移除节点总结前言 我们都知道,在框架中,当dom节点发生变化时&#xff0…

CSS初学的简单样式

CSS导航条 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><style type"text/css">*{margin: 0;padding: 0;}.nav{list-style: none;background-color: blueviolet;width: 500px;margin:50p…

CSS风车

CSS 风车 添加边框后不改变原本设计的大小&#xff1a; Box-sizing:border-box&#xff1b;<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><style type"text/css">*{margin: 0;padding: 0…

ES6中的方法-1

ES6 的方法 1、let关键字* 在块级作用于有效* 不能重复声明* 不会预处理&#xff0c;不存在变量提升2、const关键字* 不能修改* 其他等同let3、变量解构赋值例&#xff1a;*对象解构let obj{username:kobe,age:39}let {username,age}objconsole.log(username)*数组解构let arr[…

实现Promise

在编写之前首先要了解一下promise有哪些特性: 构造函数有一个函数executor里面包含两个参数&#xff08;resolve,reject&#xff09;resolve成功时执行成功的回调reject失败时执行失败的回调三种状态 pending&#xff08;初始状态&#xff09;fulfilled&#xff08;操作成功&a…

antd上传图片及表单内容

antdnode.js实现图片上传&#xff08;图片和表单同提交&#xff09; 1、 前端实现 import React from react; import { connect } from react-redux; import { RightCircleOutlined, UploadOutlined } from ant-design/icons; import { Input, Form, Button, Upload } from a…