也许很多人像我一样,觉得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进阶系列之内存空间的更多相关文章

  1. 【 D3.js 进阶系列 】 进阶总结

    进阶系列的文章从去年10月开始写的,晃眼又是4个多月了,想在年前总结一下. 首先恭祝大家新年快乐.今年是羊年吧.前段时间和朋友聊天,聊到十二生肖里为什么没猫,我张口就道:不是因为十二生肖开会的时候猫迟 ...

  2. 【 D3.js 进阶系列 — 4.0 】 绘制箭头

    转自:http://www.ourd3js.com/wordpress/?p=660 [ D3.js 进阶系列 — 4.0 ] 绘制箭头 发表于2014/12/08 在 SVG 绘制区域中作图,在绘制 ...

  3. 【 D3.js 进阶系列 — 1.1 】 其它表格文件的读取

    CSV 表格文件是以逗号作为单元分隔符的,其他还有以制表符 Tab 作为单元分隔符的 TSV 文件,还有人为定义的其他分隔符的表格文件.本文将说明在 D3 中怎样读取它们. 1. TSV 表格文件是什 ...

  4. 【 D3.js 进阶系列 — 1.2 】 读取 CSV 文件时乱码的解决方法

    在 D3 中使用 d3.csv 读取 CSV 文件时,有时会出现乱码问题. 怎么解决呢? 1. 乱码问题 使用 d3.csv 读取 xxx.csv 文件时.假设 xxx.csv 文件使用的是 UTF- ...

  5. JS进阶系列之作用域链

    在之前写的进阶系列里面,提到了执行上下文在创建阶段,要创建变量对象.确定作用域链还有确定this的指向,本次将重点讲解一下作用域链. JavaScript代码的执行过程 在讲解作用域链之前,首先了解一 ...

  6. 【 D3.js 进阶系列 — 6.1 】 缩放的应用(Zoom)

    缩放(Zoom)是另一种重要的可视化操作,主要是使用鼠标的滚轮进行. 1. zoom 的定义 缩放是由 d3.behavior.zoom() 定义的. var zoom = d3.behavior.z ...

  7. 【 D3.js 进阶系列 — 2.1 】 力学图的事件 + 顶点的固定

    本章讨论在力学图中经常使用到的事件( Event ),然后对[p=555">进阶 - 第 2.0 章]的人物关系图进行改进.使用户可以固定拖拽的对象. 在[入门 - 第 9.2 章]和 ...

  8. JS进阶系列之闭包

    刚刚总结完作用域链,我觉得很有必要马上对闭包总结一下,因为,之前也写过自己对闭包的理解,那时候只知道,闭包就是可以访问别的函数变量的函数,就是在函数里面的函数就叫做闭包,可是并没有深入探究,为什么,可 ...

  9. 【 D3.js 进阶系列 — 1.0 】 CSV 表格文件的读取

    在入门系列的教程中.我们经常使用 d3.json() 函数来读取 json 格式的文件.json 格式非常强大.但对于普通用户可能不太适合,普通用户更喜欢的是用 Microsoft Excel 或 O ...

随机推荐

  1. 一起做RGB-D SLAM (2)

    第二讲 从图像到点云 本讲中,我们将带领读者,编写一个将图像转换为点云的程序.该程序是后期处理地图的基础.最简单的点云地图即是把不同位置的点云进行拼接得到的. 当我们使用RGB-D相机时,会从相机里读 ...

  2. solr客户端的使用

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAP0AAACqCAYAAABmvkmzAAAACXBIWXMAAA7JAAAOygG3NjBLAABkG0

  3. CentOS6.5 升级 Python 2.7 版本

    转载请注明出处http://write.blog.csdn.net/mdeditor 目录 目录 前言 安装Python-279 解决YUM与Python279的兼容问题 前言 CentOS 6.5中 ...

  4. MVC杂碎笔记

    MVC页面中@相当于aspx中的<%%>一样,@后面可以写代码的,一般用来放变量的 --  在Controller中方法的前面加[HttpGet]表示该方法只处理http的 GET 请求, ...

  5. nodejs加WebSocket,聊天工具

    1.WebSocket必须要与服务器连接,所以这里采用node起服务,这里用到了ws,,也有人用nodejs-websocket 2.首先 npm install ws 3.新建一个server.js ...

  6. JQ 给textarea赋值

    <textarea id='t1'></textarea> 下面是 jq赋值的三种方式 $("#t1").text("AAA"); $( ...

  7. ServiceStack DotNet Core前期准备

    下载DotNet Core SDK 下载地址:https://dotnet.microsoft.com/download. 安装完成之后通过cmd的命令行进行确认. 官方自带的cmd比较简陋,可以用c ...

  8. nginx 参考文章汇总

    Nginx 反向代理.负载均衡.页面缓存.URL重写及读写分离详解: http://freeloda.blog.51cto.com/2033581/1288553 Nginx开发从入门到精通: htt ...

  9. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

  10. SpringBoot之统一异常处理

    异常,不仅仅是程序运行状态的描述,还可以使得代码编写更加的规范   1.自定义异常:FieldValueInvalidException package com.geniuses.sewage_zer ...