JavaScript之浅谈内存空间

JavaScipt 内存自动回收机制

在JavaScript中,最独特的一个特点就是拥有自动的垃圾回收机制(周期性执行),这也就意味者,前端开发人员能够专注于业余,从而减少在内存的管理,提高开发的效率。

用户自定义的对象、函数,但这些都是我们肉眼不可见的,而是依靠在外部的媒介“内存条”中,自动垃圾回收的本质也就是找出已不再使用的变量、函数,释放其占用的内存空间

当不再需要某样东西时会发生什么? JavaScript 引擎是如何发现并清理它?

可达性

JavaScript 中内存管理的主要概念是可达性。

简单地说,“可达性” 值就是那些以某种方式可访问或可用的值,它们被保证存储在内存中。

固有的可达值(根)

  • 本地函数的局部变量和参数

  • 当前嵌套执行上下文其他函数的变量和函数

  • 全局变量

如果引用或者引用链可以通过根访问到任何其他值,则认为该值是可访问的

实际上网页的元素就是由一个个对象构建成了一个dom树(特殊的图结构)(树结构是单向,图结构是双向的,)

通过JavaScipt提供的api我们可以找到页面上指定元素的对象,并对其进行操作

每一个DOM元素对象都可以看作是一个根,我们可以还可以访问自身元素的亲戚

  • 父元素

  • 兄弟元素

  • 祖先元素

  • 后代元素

单项引用

    var user = {
name : 'EYS',
}

这里的箭头表示一个对象引用,全局变量 "user" 引用对象{name : 'EYS'} user对象中的name属性存储了一个基本类型的数据

但如果user的值被覆盖,则引用丢失

    user = null;

现在user变成不可达的状态,没有办法访问之前的值,他们之间没有联系,就被JavaScript引擎发现他了!!!然后就把他丢到小黑屋去了,自动释放了它所占用的内存空间


#### 双向引用

    // user具有对象的引用
var user = {
name: "John"
};
var admin = user; //引用传递

该对象仍然可以通过 admin 全局变量访问,所以它在内存中。如果我们也覆盖admin,那么它可以被释放。

相互关联的对象

    function marry (man, woman) {
woman.husban = man;
man.wife = woman; return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
})

产生的内存结构:

内存中的图片变成:

现在让我们删除两个引用:

    delete family.father;
delete family.mother.husband;

仅仅删除这两个引用中的一个是不够的,因为所有对象仍然是可访问的。

输出引用无关紧要。只有传入的对象才能使对象可访问,因此,John 现在是不可访问的,并将从内存中删除所有不可访问的数据。

垃圾回收之后:


但是如果我们把这两个都删除,那么我们可以看到 John 不再有传入的引用:

无法访问的数据块

    family = null;

但是如果我们把这两个都删除,那么我们可以看到 John 不再有传入的引用:

“family”对象已经从根上断开了链接,不再有对它的引用,因此下面的整个块变得不可到达,并将被删除。

回收过程

标记清除 (推荐)

分为『进入环境』和『离开环境』

进入环境 : 指变量进入的执行环境

离开环境 : 指变量完成任务,离开了执行的环境

垃圾收集器会在脚本运行的时候给存储在内存中的所有变量都加上标记

它会去掉环境中的变量以及被环境中的变量引用的变量的标记

而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了

最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间

引用计数 (不推荐)

含义 : 跟踪记录每个值被引用的次数

  • 当用户声明了一个变量并将一个引用类型值赋给该变量时,则这个值的应用次数就为1 【声明变量并赋值】

  • 如果同一个值又被赋给另一个变量,则该值的引用次数加 1 【变量的值传递】

  • 如果包含这个值引用的变量被覆盖了,则之前的值的应用次数减1 【覆盖变量之前的值】

  • 当这个值的引用次数变成 0 时,则说明没有办法再访问这 个值了,因而就可以将其占用的内存空间回收回来。 【变量回收】

这种机制其实在js中并不常用,因为这种机制会产生循环引用的问题,『循环引用』指的是对象 A 中包含一个指向对象 B 的指针,而对象 B 中也包含一个指向对象 A 的引用。对于像js类的自动回收机制的语言来说,需要额外手动的去释放内存,其实并不友好。

在学习内存空间之前,我们需要对三种数据结构有一个清晰的理解。他们分别是堆(heap)栈(stack)队列(queue)

三种数据结构

一、栈(Stack)数据结构

JavaScript中并没有严格意义上区分栈内存与堆内存

如JavaScript的执行上下文(关于执行上下文我会在下一篇文章中总结)。执行上下文的执行顺序借用了栈数据结构的存取方式(也就是后面我们会经常提到的函数调用栈)。因此理解栈数据结构的原理与特点十分重要。

JavaScript的数据类型分为两种 : 基本类型,引用类型

我们可以简单粗暴的理解 基本类型数据是存储在栈,引用类型的数据是存储在堆中,等待变量建立引用关系

要简单理解栈的存取方式,我们可以通过类比乒乓球盒子来分析。如下图左侧。

基本特征为 : 先进后出,后进先出

二、堆(Heap)数据结构

堆数据结构是一种树状结构。它的存取数据的方式,则与书架与书非常相似。

书虽然也整齐的存放在书架上,但是我们只要知道书的名字,就可以很方便的取出我们想要的书,而不用像从乒乓球盒子里取乒乓一样,非得将上面的所有乒乓球拿出来才能取到中间的某一个乒乓球。好比在JSON格式的数据中,我们存储的key-value是可以无序的,因为顺序的不同并不影响我们的使用,我们只需要关心书的名字。

三、队列

队列是一种先进先出(FIFO)的数据结构。正如排队过安检一样,排在队伍前面的人一定是最先过检的人。用以下的图示可以清楚的理解队列的原理。

JavaScript之浅谈内存空间的更多相关文章

  1. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  2. Qt浅谈内存泄露(总结)

    Qt浅谈内存泄露(总结) 来源 http://blog.csdn.net/taiyang1987912/article/details/29271549 一.简介 Qt内存管理机制:Qt 在内部能够维 ...

  3. C学习笔记(11)--- 可变参数,浅谈内存管理 【C基础概念系列完结】

    1.可变参数(variable arguments): 可变参数允许您定义一个函数,能根据具体的需求接受可变数量的参数. int func(int, ... )             (函数 fun ...

  4. javascript数组浅谈2

    上次说了数组元素的增删,的这次说说数组的一些操作方法 join()方法: ,,] arr.join("_") //1_2_3 join方法会返回一个由数组中每个值的字符串形式拼接而 ...

  5. javascript数组浅谈1

    最近心血来潮要开始玩博客了,刚好也在看数组这块内容,第一篇就只好拿数组开刀了,自己总结的,有什么不对的地方还请批评指正,还有什么没写到的方面也可以提出来我进行完善,谢谢~~ 首先,大概说说数组的基本用 ...

  6. 【javascript】浅谈javaScript的深拷贝

        前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...

  7. JAVA NIO之浅谈内存映射文件原理与DirectMemory

    JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...

  8. 【NIO】NIO之浅谈内存映射文件原理与DirectMemory

    Java类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...

  9. JavaScript闭包浅谈

    ------------------- 作者:willingtolove: 本文链接:http://www.cnblogs.com/willingtolove/p/4745889.html 1. 变量 ...

随机推荐

  1. iOS 图片加载和处理

    一.图片显示 图片的显示分为三步:加载.解码.渲染.解码和渲染是由 UIKit 进行,通常我们操作的只有加载. 以 UIImageView 为例.当其显示在屏幕上时,需要 UIImage 作为数据源. ...

  2. 从零搭建一个SpringCloud项目之Feign搭建

    从零搭建一个SpringCloud项目之Feign搭建 工程简述 目的:实现trade服务通过feign调用user服务的功能.因为trade服务会用到user里的一些类和接口,所以抽出了其他服务需要 ...

  3. .net core系统跨平台部署手册

    前言 .net core跨平台版本基于.net core 3.1 SDK开发,剥离原来的基于MS Office进行文档转换功能的模块,使用基于开源跨平台的LibreOffice进行文档转换的模块.以此 ...

  4. 8.MSFvenom

    Meterpreter 01 Meterpreter API调用 Meterpreter提供了多种APl调用,在编写自己的脚本时可以使用这些API来提供额外功能或定制功能. 关于ruby的更多信息,请 ...

  5. NKOJ4241 蚯蚓 (【NOIP2016 DAY2】)

    问题描述 输入格式 第一行包含六个整数n,m,q,u,v,t,其中:n,m,q的意义见问题描述: u,v,t均为正整数:你需要自己计算p=u/v(保证0<u<v)t是输出参数,其含义将会在 ...

  6. 1127: 【入门】A类多?B类多?

    1127: [入门]A类多?B类多? 时间限制: 1 Sec 内存限制: 16 MB 提交: 3537 解决: 2406 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 一个自然数转换 ...

  7. HDU-1421-搬寝室(01背包改编版)

    搬寝室是很累的,xhd深有体会.时间追述2006年7月9号,那天xhd迫于无奈要从27号楼搬到3号楼,因为10号要封楼了.看着寝室里的n件物品,xhd开始发呆,因为n是一个小于2000的整数,实在是太 ...

  8. SWUST OJ 1075 求最小生成树(Prim算法)

    求最小生成树(Prim算法) 我对提示代码做了简要分析,提示代码大致写了以下几个内容 给了几个基础的工具,邻接表记录图的一个的结构体,记录Prim算法中最近的边的结构体,记录目标边的结构体(始末点,值 ...

  9. 使用 Spring data redis 结合 Spring cache 缓存数据配置

    使用 JavaConfig 方式配置 依赖 jar 包: jedis.spring-data-redis 首先需要进行 Redis 相关配置 @Configuration public class R ...

  10. DVWA系列精品教程:2、命令注入

    文章更新于:2020-04-11 注:如何搭建环境参见:搭建DVWA Web渗透测试靶场 DVWA之命令注入漏洞 一.介绍 1.1.官方说明 1.2.总结 二.命令注入实践 2.1.安全级别:LOW ...