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. [React]Hook初探

    Hook是什么 Hook是React从16.8开始支持的特性,使用Hook可以在不使用class时使用state Hook支持在不需要修改组件状态的情况下复用逻辑状态,从而解决使用render pro ...

  2. 面试常问的 Java 虚拟机运行时数据区

    写在前面 本文描述的有关于 JVM 的运行时数据区是基于 HotSpot 虚拟机. 概述 JVM 在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以 ...

  3. "图片组件"组件:<pic> —— 快应用组件库H-UI

     <import name="pic" src="../Common/ui/h-ui/media/c_pic"></import> & ...

  4. 如何使用npt结合crontab实现集群之间的时间同步

    当我们每个机器的时间都不一致时,假如有一个定时任务,定的10点启动执行.结果namenode十点了启动任务,可是分配到的执行节点DataNode才九点五十导致任务执行失败怎么办?这就需要将机器之间的时 ...

  5. xargs与exec区别

    平时使用find命令查找出文件的时候有时候后面有时候用-exec有时候用管道加xargs,这2个到底有什么不同?下面就这2个的不同做简单介绍. 零.实验环境 [root@osker /]# find ...

  6. 刨根问底系列(1)——虚假唤醒(spurious wakeups)的原因以及在pthread_cond_wait、pthread_cond_singal中使用while的必要性

    刨根问底之虚假唤醒 1. 概要 将会以下方式展开介绍: 什么是虚假唤醒 什么原因会导致虚假唤醒(两种原因) 为什么系统内核不从根本上解决虚假唤醒这个"bug"(两个原因) 开发者如 ...

  7. Hibernate框架 jar包介绍

    一直使用my eclipse集成的Hibernate来学习.最近在写hibernate的日记,写到搭建hibernate框架的时候才发现自己对hibernate的内容还是不了解,决定自己手动搭建一下. ...

  8. Spring--开篇 (spring优缺点、模块组件、各个jar包详解)

    Spring--开篇 分类: SSH&EJB2012-11-23 15:25 4369人阅读 评论(13) 收藏 举报 javaJavaJAVAspringSpringwebWebWEB框架 ...

  9. Property [*****] not found on type [com.erp.pojo.ErpSupplier]

    我实体类里用的是 springboot 里@Slf4j   @Data  注解式写的  这样可以减少代码量 ,但是遇到一个问题影响我好长时间 出现了这个错误  Property [*****] not ...

  10. day01,了解gcc

    今天主要是学一下gcc 功能选项: 一. 1.  gcc -E:表示预处理,把指令处理掉 2.gcc -o:改变目标文件名称 3. gcc -c: 表示只编译不链接(也就是不生成a.out) 4. g ...