《JavaScript》- 理解内存空间

说起内存空间,应该不少人对它的认知还是比较模糊,因为 JavaScript 本身具有垃圾回收机制,对于前端开发来说,内存空间不是常提起的概念,所以容易被大家忽视了,而往往被忽视的内容,就是你掉坑里的缘由


《JavaScript》- 理解内存空间

堆 / 栈 / 队列

说起内存空间前,需要理解三个数据结构的概念,也就是堆(heap) / 栈(stack) / 队列(queue)

1.1. 堆数据结构

树状结构,而对于数据的存取方式,我们可以举个简单的例子来理解:人山人海的广场,我要找你,如何找?拿一个大喇叭大吼你的名字,你听到,是不是自然就招手示意,出列了?不用列队,大家都散乱的站在广场上,但我能通过你的名字等指定信息立马找到你,与顺序无关,就好比 Json 采用 key-value 无序存储一样,并不影响我们取值

1.2. 栈数据结构

理解栈数据的存取方式,我们可以举个简单的子弹与子弹夹的关系为例:装弹环节,一颗子弹一颗子弹的往子弹夹里面塞,而等到射击的时候,第一颗子弹即最先装入的子弹是不是在底部,是不是最后才被射击出来?这就是栈数据结构的特点:先进后出,后进先出

1.3. 队列

队列,顾名思义,就像排队过安检一样,排在前面的人,先过安检,你想插队吗?被插队的人不乐意,保安也不允许你插队,这也就是队列的特点:先进先出(FIFO)

《JavaScript》- 理解内存空间

基本数据类型

我们知道,JavaScript有5种基本数据类型,即 Number / String / Null / Object / Undefined,这些类型在内存空间中占用的大小是固定的,存储在栈内存中,按值访问,我们可以直接操作保存在变量内的值。说到基本数据类型,另外提一下相对比较特殊的点,即 Null / Undefined,这两种数据类型都只有一个值,就是 null / undefined,需要注意的是,如果用 typeof 对值为 null 的变量进行检测时,得到的结果是 object,也就是说 null == undefined,但 null !== undefined,且 null 是 JavaScript 的保留字,但 undefined 却不是。另外一个虽然不是基本的数据类型,但是一个比较特殊的值,顺带也提一下,避免某些时候掉进坑里了,就是一个特殊的数量值 NaN,记住 typeof NaN === 'number' 返回的结果为 true,即 isNaN(NaN) 的结果为 true(isNaN 为 JavaScript 内置函数),如若要判断变量值是否为数字,可以自行封装函数,结合 isFinite 函数进行判断。

《JavaScript》- 理解内存空间

引用数据类型

引用类型的数据值,大小是不固定的,栈内存存储的是引用数据类型的引用地址,实际值是存储在堆内存中,按引用访问。JavaScript 是不允许直接访问堆内存中的数据,所以在操作对象或数据等引用数据类型时,实际上是在操作对象的引用而非真正的对象。我们举个简单的例子来印证上述的内容

<code>var m = 'https://blog.makeit.vip';
var miit = {blog: '博客', mall: '商城'};

// 这时候得到 m 的结果是什么 ?
var k = m;
k = 'Nice Job';
console.log(m);

// miit.blog 的结果是什么 ?
var vip = miit;
vip.blog = 'makeit\\'s blog';
console.log(miit.blog);

// 很显然,第一个得到 m 的结果依然是 https://blog.makeit.vip
// m 赋值与 k,为 k 分配栈内存进行存储,m 与 k 各自在不同的栈空间中,
// 操作 k 或 m,相互之间并不会有任何干扰,相互之间是互不干扰的

// 第一个的结果是 makeit's blog
// miit 为引用数据类型,栈内存中存储的只是引用地址,在 miit 赋值与 vip 后,

// 为 vip 变量分配了栈空间,存储的同样是引用地址,指向的是同一个存储在堆内存中的变量值
// 所以 vip 的操作直接影响了 miit 引用地址所指向的堆内存中的数据(同一个)/<code>

理解了内存空间,上述示例中的结果是不是就是理所当然了?那么来了,JavaScript 是如何管理内存空间的?


分享到:


相關文章: