一、 javaScript数据类型
javaScript 数据类型分为:基本数据类型、引用数据类型
基本数据类型
分类:Number、String、Boolean、Null、Undefined、Symbol。
存储地址:栈。
引用数据类型
分类:Object、Array、Function。
存储地址:堆。
二、存储地址
栈
特点:小、速度快、有序。
通常情况下,栈的内存空间不会设置很大(因为栈空间是用来存放执行上下文的,如果栈空间设置的很大,会影响切换执行上下文的速度),栈一般用于存储一些 原始类型 的小数据。
堆
特点:大、速度慢、无序。
堆的内存空间很大,常用于存储类似 引用类型 的这样的大数据。
三、垃圾回收机制
栈内存如何回收
当函数在执行时,有一个记录当前执行状态的指针(ESP)指向它。
当此函数被执行结束后,ESP指针指向下一个执行函数。虽然此时上一个函数还存在于占内存中,但下一个函数的执行可能会覆盖掉它。
堆内存如何回收
这里主要介绍:V8引擎的垃圾回收机制。
原理:
1、内存划分
引擎将堆内存分为两个部分:新生代、老生代
新生代:存放生存时间较短的对象 -------由副垃圾回收器回收。
老生代:存放生存时间较长的对象 -------由主垃圾回收器回收。
2、副垃圾回收器
副垃圾回收器将 新生代内存空间 分为两个部分:对象区域 和 空闲区域。
新加入的对象都会被放入对象区域,当对象区域快满的时候,执行一次回收。
注意:如果对象区域很大,每次清理的时间就会很长,所以对象区域一般都很小,但也很容易被放满。所以经过两次垃圾回收之后依然存活的对象会被放入老生代。
回收过程:副垃圾回收器对 对象 区域中的垃圾进行标记,标记完成之后,进入垃圾清理阶段,并将活跃的对象移入空闲区域(这时候会出现许多内存不连续的空白区域),同时还会把他们有序的排列起来,这个排列的过程就相当于做了内存整理。执行完上述操作后,再将 对象区域 与 空闲区域 的的角色相调换。
3、主垃圾回收器
主要采用 标记清除法 进行垃圾回收。
标记:
从一组根元素开始,递归遍历这组根元素,在遍历过程中能够被遍历到的元素成为活动对象,没有被遍历到的元素则是垃圾数据。
清除:
问题1:因为主垃圾回收器主要用来回收内存区域大,存储数据大的垃圾,所以如果对所有的垃圾数据依次清除,会带来很多的内存碎片。
解决:标记整理(在标记的过程中,将所有活跃的对象都向一边移动,最后清除掉边界以外的垃圾)。
问题2:JavaScript 是运行在主线程之上的,一旦执行垃圾回收算法,都需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行,非常的耗时。
解决:让垃圾回收操作和js脚本交替执行(类似时间片)。
思考:闭包之所以会带来内存泄漏的问题,主要是因为不能对其变量进行垃圾回收,如何解决这个问题呢?
答案:使用完内存变量后,将此变量指向null。