JS进阶系列之内存空间
也许很多人像我一样,觉得JS有垃圾回收机制,内存就可以不管了,以至于在全局作用域下定义了很多变量,自以为JS会自动回收,直到最近,看了阮一峰老师,关于javascript内存泄漏的文章时,才发现自己写的代码,存在很严重的内存泄漏问题,再者,因为忽略对内存的学习,导致后面很多进阶概念很模糊,比如深复制与浅复制的区别,比如闭包、作用域链等等。
堆与栈
与C/C++不同,JavaScript语言没有严格意义上,区分堆与栈,所以我们可以理解为,JavaScript所有的数据都是存放在堆内存
中。
不过,在某些场景下,我们仍然需要借助堆栈数据结构来处理,所以有必要理解一下这两个数据结构的区别。
栈:也叫做堆栈
栈数据结构的一个特点就是后进先出
,好比羽毛球盒子,在一头放羽毛球,在另外一头取羽毛球。
堆数据结构,好比书架上的书,虽然已经按顺序放好了,但是我们只要知道书的名字,就可以对应的取下来,类似于JSON对象中的key-value
。
变量对象与基本数据类型
JavaScript中的数据类型大致分为,基本数据类型
与引用数据类型
,上文提到,JavaScript中所有的数据都是存放在堆内存
中,但是,这里提到的变量对象
(在执行上下文创建阶段生成),由于它有特殊的职能,所以在理解上就把它与堆内存单独分开了,如下图所示:
一般变量对象
里面存放的是基本数据类型
,包括Undefined、Null、Boolean、Number、String
,它们到是按值访问
的。
demo01
var a = 20;
var b = a;
b = 30;
console.log(a);//20
上面这段代码指的是,在变量对象中执行数据复制的时候,其实系统会自动为新的变量分配一个新的值,所以a与b其实已经是完全独立的两个变量,只是值一样而已。
堆内存与引用数据类型
javascript中的引用数据类型
是存放在堆内存
中的,但是不同于变量对象
,javascript是不允许直接访问堆内存中的数据,所以如果我们要访问引用数据类型的时候,采用的是按引用访问
,其实就是在变量对象
中存放了一个指向对象的句柄,可以理解为一个地址,要访问堆内存中的对象,就要通过这个引用句柄来访问,例如上图中的d变量,就是一个指向对象的地址。
demo02
var m = { a:10,b:20};
var n = m;
n.a = 15;
console.log(m.a);//15
上面这段代码指的是执行引用类型数据的复制时,在变量对象中会分配一个新的值,来存放新的变量,但是这两个变量的地址是一样的,相当于指向的对象是一样的,所以各自改变对象里面的属性值,会互相影响,如下图
内存泄漏
上面讲解了JavaScript中的内存空间,接下来就要讲解,我写这篇文章的初衷,就是我代码中严重的内存泄漏
内存泄漏:就是不再用到的内存,但是没有及时释放,就叫做内存泄漏
有些语言必须手动释放内存,程序员负责内存的管理,例如C语言
char *buffer;
buffer = (char*) malloc(42);
//do something with buffer
free(buffer);
这里malloc
就是负责分配内存,free
是负责释放内存。
那么JavaScript中的垃圾回收机制又是怎么一回事呢?
垃圾回收机制
以前我一直天真的以为,垃圾回收机制就像人工智能一样,会自动帮你识别出不用的内存,然后释放掉,然而真相只有一个
垃圾回收机制的原理就是,使用引用计数
法,就是语言引擎有一张“引用表”,保存了内存里面所有的资源的引用次数,就像下面这样
但是如果一个值不再需要了,引用数却不为0,垃圾回收机制是无法释放这块内存,从而导致``内存泄漏```
例如:
const arr = [1,2,3,4,5];
console.log('hello world");
arr的引用次数为1,尽管后面不再使用arr了,但是它还会持续占用内存,所以一般要这样处理
const arr = [1,2,3,4,5];
console.log('hello world");
arr = null;
让arr的指向为空,垃圾回收机制就会默认它的引用数为0而回收掉。
避免内存泄漏
在局部作用域中,等函数执行完毕,变量就没有存在的必要了,js垃圾回收机制很快做出判断并且回收,但是对于全局变量,很难判断什么时候不用,所以,经验之谈就是,尽量少使用全局变量。
我们在使用闭包的时候,就会造成严重的内存泄漏,因为闭包的原因,局部变量会一直保存在内存中,所以在使用闭包的时候,要多加小心。
JS进阶系列之内存空间的更多相关文章
- 【 D3.js 进阶系列 】 进阶总结
进阶系列的文章从去年10月开始写的,晃眼又是4个多月了,想在年前总结一下. 首先恭祝大家新年快乐.今年是羊年吧.前段时间和朋友聊天,聊到十二生肖里为什么没猫,我张口就道:不是因为十二生肖开会的时候猫迟 ...
- 【 D3.js 进阶系列 — 4.0 】 绘制箭头
转自:http://www.ourd3js.com/wordpress/?p=660 [ D3.js 进阶系列 — 4.0 ] 绘制箭头 发表于2014/12/08 在 SVG 绘制区域中作图,在绘制 ...
- 【 D3.js 进阶系列 — 1.1 】 其它表格文件的读取
CSV 表格文件是以逗号作为单元分隔符的,其他还有以制表符 Tab 作为单元分隔符的 TSV 文件,还有人为定义的其他分隔符的表格文件.本文将说明在 D3 中怎样读取它们. 1. TSV 表格文件是什 ...
- 【 D3.js 进阶系列 — 1.2 】 读取 CSV 文件时乱码的解决方法
在 D3 中使用 d3.csv 读取 CSV 文件时,有时会出现乱码问题. 怎么解决呢? 1. 乱码问题 使用 d3.csv 读取 xxx.csv 文件时.假设 xxx.csv 文件使用的是 UTF- ...
- JS进阶系列之作用域链
在之前写的进阶系列里面,提到了执行上下文在创建阶段,要创建变量对象.确定作用域链还有确定this的指向,本次将重点讲解一下作用域链. JavaScript代码的执行过程 在讲解作用域链之前,首先了解一 ...
- 【 D3.js 进阶系列 — 6.1 】 缩放的应用(Zoom)
缩放(Zoom)是另一种重要的可视化操作,主要是使用鼠标的滚轮进行. 1. zoom 的定义 缩放是由 d3.behavior.zoom() 定义的. var zoom = d3.behavior.z ...
- 【 D3.js 进阶系列 — 2.1 】 力学图的事件 + 顶点的固定
本章讨论在力学图中经常使用到的事件( Event ),然后对[p=555">进阶 - 第 2.0 章]的人物关系图进行改进.使用户可以固定拖拽的对象. 在[入门 - 第 9.2 章]和 ...
- JS进阶系列之闭包
刚刚总结完作用域链,我觉得很有必要马上对闭包总结一下,因为,之前也写过自己对闭包的理解,那时候只知道,闭包就是可以访问别的函数变量的函数,就是在函数里面的函数就叫做闭包,可是并没有深入探究,为什么,可 ...
- 【 D3.js 进阶系列 — 1.0 】 CSV 表格文件的读取
在入门系列的教程中.我们经常使用 d3.json() 函数来读取 json 格式的文件.json 格式非常强大.但对于普通用户可能不太适合,普通用户更喜欢的是用 Microsoft Excel 或 O ...
随机推荐
- Sql Server 2016 Always On集群搭建
第一步,配置好windows环境 第二步 (配置内容较多--需单写) 需要做windows集群 安装WSFC集群组件 直接在Windows服务器管理工具中,增加功能模块,集群故障转移模块 并增加节点 ...
- 7.MQTT网页客户端连接MQTT服务器的问题WebSocket connection to 'ws://XXX:1883/' failed: Connection closed before receiving a handshake response
问题描述:MQTT.js提供了连接MQTT的一套javascipt的方法,可供前端连接到MQTT服务器,也可以作为脚本测试.以脚本形式,用nodejs运行,是没有问题的,能够正常连接并且发送报文.但是 ...
- SQLyog恢复数据库报错解决方法【Error Code: 2006 - MySQL server has gone away】
https://blog.csdn.net/niqinwen/article/details/8693044 导入数据库的时候 SQLyog 报错了 Error Code: 2006 – MySQL ...
- sdut2613(This is an A+B Problem)大数加法(乘法)
#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>u ...
- mui笔记
1.关闭当前页面执行上一个页面的方法 var preview = plus.webview.currentWebview().opener() //获取当前窗口的创建者,即A preview.eval ...
- http协议基础(三)几种数据传输方式
说说http协议的一些特点: 1)无状态 http协议是一种自身不对请求和响应之间的通信状态进行保存的协议,即无状态协议. 这种设置的好处是:更快的处理更多的请求事务,确保协议的可伸缩性 不过随着we ...
- discuz $_G变量
class.core.php中 global $_G; $_G = array( 'uid' => 0, 'username' => ...
- BootStrap同时显示多个Modal解决方案
使用BootStrap自带的Modal的时候,如果同时调用多个Modal,那么只能看到背景颜色加深但是看不见新的Modal页面. 问题主要是Modal的z-index有问题,重新计算z-index并赋 ...
- VS中代码对齐等快捷键
在VS2008中,选定代码后,按Ctrl+K+F组合键,可以自动进行代码对齐. 注意:要先按下Ctrl和K,再按下F,因为Ctrl+F是查找的快捷键. 也可以先按下Ctrl+K,再按下Ctrl+F. ...
- BufferedImage操作图片笔记(转)
BufferedImage是Image的一个子类,BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便的操作这个图片,通常用来做图片修改操作如大小变换.图片变灰. ...