JavaScript之浅谈内存空间
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之浅谈内存空间的更多相关文章
- 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理
[微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...
- Qt浅谈内存泄露(总结)
Qt浅谈内存泄露(总结) 来源 http://blog.csdn.net/taiyang1987912/article/details/29271549 一.简介 Qt内存管理机制:Qt 在内部能够维 ...
- C学习笔记(11)--- 可变参数,浅谈内存管理 【C基础概念系列完结】
1.可变参数(variable arguments): 可变参数允许您定义一个函数,能根据具体的需求接受可变数量的参数. int func(int, ... ) (函数 fun ...
- javascript数组浅谈2
上次说了数组元素的增删,的这次说说数组的一些操作方法 join()方法: ,,] arr.join("_") //1_2_3 join方法会返回一个由数组中每个值的字符串形式拼接而 ...
- javascript数组浅谈1
最近心血来潮要开始玩博客了,刚好也在看数组这块内容,第一篇就只好拿数组开刀了,自己总结的,有什么不对的地方还请批评指正,还有什么没写到的方面也可以提出来我进行完善,谢谢~~ 首先,大概说说数组的基本用 ...
- 【javascript】浅谈javaScript的深拷贝
前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...
- JAVA NIO之浅谈内存映射文件原理与DirectMemory
JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...
- 【NIO】NIO之浅谈内存映射文件原理与DirectMemory
Java类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...
- JavaScript闭包浅谈
------------------- 作者:willingtolove: 本文链接:http://www.cnblogs.com/willingtolove/p/4745889.html 1. 变量 ...
随机推荐
- redis++:Redis持久化 rdb & aof 工作原理及流程图 (三)
RDB的原理: 在Redis中RDB持久化的触发分为两种:自己手动触发与Redis定时触发. 针对RDB方式的持久化,手动触发可以使用: 1):save:会阻塞当前Redis服务器,直到持久化完成,线 ...
- localStorage应用(写的时间缓存在本地浏览器)
最近用了下localStorage,于是想记录加深下映象: 有关更详细的介绍,可以去看https://www.cnblogs.com/st-leslie/p/5617130.html: 我这引用了这个 ...
- 深度解析Java中的5个“黑魔法”
现在的编程语言越来越复杂,尽管有大量的文档和书籍,这些学习资料仍然只能描述编程语言的冰山一角.而这些编程语言中的很多功能,可能被永远隐藏在黑暗角落.本文将为你解释其中5个Java中隐藏的秘密,可以称其 ...
- 【php】错误日志处理
一. 错误处理: a) 在写程序的过程当中,遇到错误时,你的反应?可能比较急躁,比较烦 b) 遇到错误后:一别哭,二别闹,三别上吊,四别尿……二. 你可能会遇到的错误: a) 语法错误 i. 语法错误 ...
- MODIS系列之NDVI(MOD13Q1)一:数据下载(一)基于插件
引言: 写MODIS数据处理这个系列文章的初衷,主要是为了分享本人处理MODIS数据方面的一些经验.鉴于网上对这方面系统性的总结还比较少,我搜集资料时也是走了许多的弯路,因此希望通过此文让初学者能够更 ...
- 28 api的使用2
本文将讲解如下api的使用: Object.System.Date.DateFormat.Calendar.Integer-- int的包装类等 1. 类 Object 是类层次结构的根类.每个类都使 ...
- 9.1 ArrayList(集合)的使用,与array(数组)的对比
1.array 和ArrayList的区别? array 数组的长度是固定的,适应不了变化的需求. ArrayList集合的长度可变.大小可变. 2.为什么要用集合,它优点是什么? java是面向对象 ...
- for循环in遍历
<script> //对象本身没有length,所以不能用for循环遍历 //要用for...in...循环 var aaa = {"name":"拴住&qu ...
- 学习笔记分享之汇编---3. 堆栈&标志寄存器
前言: 此文章收录在本人的<学习笔记分享>分类中,此分类记录本人的学习心得体会,现全部分享出来希望和大家共同交流学习成长.附上分类链接: https://www.cnblogs.c ...
- re模块语法—python正则表达式
用字符串匹配实现 对于简单的匹配查找,可以通过字符串匹配实现,比如:查找以”hello”开头的字符串 此时就可以正确查找出以start开始的字符串了 python中的正则表达式模块 在python中为 ...