IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Javascript WeakSet与Set类型在引用上的区别 | “究竟什么算强引用?什么算弱引用?” -> 正文阅读

[JavaScript知识库]Javascript WeakSet与Set类型在引用上的区别 | “究竟什么算强引用?什么算弱引用?”

1.什么是引用?

? 引用,即引用计数的简称。通俗来讲可以认为是系统在管理内存时的一种凭证和依据。引用计数本身可以认为就是一个内存空间的【数字类型的固有属性】。当我们在创建一个变量的时候,系统会为我们分配一块内存,与此同时系统会给这块内存空间绑定一个名为引用计数的固有属性,并对这个固有属性设置为1。例如下图中我们编写一段简单的代码,创建一个名为num的变量并对这个num变量初始化内容为整数类型1,那么内存中的状态就如下所示:

? 特别的,内存区域的引用计数值会伴随着【指向该内存区域的变量】数量增多更增加。例如下图中如果我们在刚才的代码中新增一段话,额外再创建一个变量num2,并将num2赋值为num。那么我们就说num2变量指向了num所在的内存区域,即此时系统中就存在两个变量指向了num所在的内存区域,因此num内存区域所对应的引用计数就会被系统增加至2。

? ?那么引用计数存在的意义是什么呢?让我们暂且把这个问题放在一边,先来了解一下JavaScript中给我们提供的另一个隐形的强大助手。

2.垃圾回收机制(Garbage Collection Mechanism)

? 在JavaScript内部,系统提供了一个名为垃圾回收(Garbage Collection Mechanism)的内存管理机制。GCM会定期(每经过一段时间,具体间隔是多少不确定,是由系统决定的)来询问每一个被分配给用户使用的内存区域的引用计数。

? 如果GCM在检测引用计数的时候发现该内存区域的引用计数归零了,那么就意味着该内存区域没有被任何一个变量所指向了,而这也就意味着该内存区域也就无法再被用户通过任何一个变量在访问到。换句话说此时这块原本被系统分配给用户使用的内存变成了一个【幽灵内存】,使用权仍然在用户,但是用户却无法使用它。这就是我们很多人所熟知的【内存泄漏】。

? 或许我们会觉得一个变量两个变量所占有的内存不会很大,对系统负载不会造成什么影响。但是需要说明的是,程序的执行大多是长时间运行的状态,而变量所造成的内存泄漏也会不断的积累,最终引发不可预知的后果,因此解决内存泄漏就势在必行。幸运的是,GCM就是解决这个问题的。

? GCM在询问每一个被分配给用户使用的内存区域的引用计数的时候,如果发现该内存区域的引用计数发生了归零事件,则GCM会立即将该内存区域的使用权“释放”,将该内存区域的使用权由用户变更为系统,也就是说这块幽灵内存又回到了系统的管辖范围之内,系统可以再次将这块内存空间分配给其他某个变量再次使用了。

? (ps:JavaScript中设置变量为null并不会真的释放内存,只不过释放的是对于该区域内存的使用权,这部分至少在这里暂时不用了解,只需要了解引用计数的变化就可以了。)

?3.强引用?弱引用?

? 可以简单粗暴的一点来了解:

  • 强引用:变量赋值以后,变量所指向的内存空间的引用计数+1
  • 弱引用:变量赋值以后,变量所指向的内存空间的引用计数不变

? 需要注意的是,正常情况下我们创建变量所带来的引用计数变化都属于强引用范畴,也就是说变量的赋值大多都会产生引用计数的增加,而该变量所产生的引用计数增加会直到该变量被释放时才会减少。而这也是为什么我们要在编码的过程当中建议尽可能少去使用全局变量的一个重要原因。

4.WeakSet与Set数据类型在引用上的区别?

? 注意本文并不去纠结WeakSet数据类型与Set数据类型的使用方式与特性,很多前辈已经将他们解释的非常清楚了。这里我们只来探讨一下有关于引用计数方面的问题。废话不多说,直接上代码。

4.1.WeakSet弱引用效果

? 首先是WeakSet弱引用集合。我们创建一个弱引用集合wset,然后创建一个带有属性的对象frank,然后将frank对象的属性uname添加至wset中。(ps:WeakSet要求存入的内容必须是Object类型的数据。)

    const wset = new WeakSet();
    var frank = {
        uname:{ temp:"abc" }
    };
    wset.add(frank.uname);
    console.log(frank);
    console.log(wset);
    console.log("------------");

?输出的结果如下所示,一切正常。

?再然我们将frank对象的uname属性删除,并直接将frank对象指null释放变量的引用。此时根据我们前面内容的分析可以知道,对于frank.uname指向的内存区域而言,由于我们删除了frank对象的uname属性,因此frank.uname对于该内存空间的引用已经被释放了。而又由于我们删除了frank对象对于内存空间的引用,因此frank对于该内存空间的引用也已经被释放了。所以目前原本【frank.uname】所对应的内存区域的引用计数必然已经归零。因此GCM会将内存释放。

? 等等!不是还有一个WeakSet的实例wset中保存着这个对象的引用吗?他的引用计数怎么就归零了?其实这就是WeakSet的特性,弱引用!就是保存引用的时候并不增加引用计数,并不影响GCM对于内存区域的管理与释放,所以才叫“弱”引用

    delete frank.uname;
    console.log(frank);
    console.log(wset);
    console.log("------------");
        
    frank = null;
    console.log(frank);
    console.log(wset);

而执行的效果也果然如我们分析所示。虽然指向仍然存在,但是该区域的内存已经被释放,因此wset中的内容就已经消失不见了。

ps:由于JavaScript的GCM并不受我们手动控制,因此在执行的过程中并不会每一次都会能够成功的将内存空间释放,大概率需要多执行几次,大多数情况下不会被释放也是正常情况。毕竟GCM的时间间隔实在迷的很

?4.2.Set强引用效果

? 对比来看,直接上代码:

    const sset = new Set();
    var frank = {
        uname:{ temp:"abc" }
    };
    sset.add(frank.uname);

    console.log(frank);
    console.log(sset);
    console.log(sset.size);
    console.log("------------");
        
    delete frank.uname;
    console.log(frank);
    console.log(sset);
    console.log(sset.size);
    console.log("------------");
        
    frank = null;
    console.log(frank);
    console.log(sset);
    console.log(sset.size);

? ?无论执行多少次,set集合中的内容都永远不会发生变化。因此证明集合类型中对于内存区域的引用是强引用,即引用计数会发生+1,从而导致GCM在查询该内存区域时引用计数永远不归零的情况发生。所以该区域的内存空间永远不会被释放,

?

?

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-13 11:21:44  更:2021-10-13 11:22:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:29:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码