js内存图与垃圾回收

2,315 阅读3分钟
原文链接: zhuanlan.zhihu.com

在你决定是否看这篇文章之前,试做以下四道小测。做对了,说明你对js内存的问题有很清晰的理解,没必要往下看;如果做错了,那么恭喜你,这篇文章将给你一个提升自己的机会。

问题1:

问题2:

问题3:

问题4:

回答完毕?请按Ctrl + PageDown到本文最底部查看答案。

做对的同学,good job! 请按Ctrl + W关闭本页,因为你没有必要浪费时间看完后边内容。

做错的同学,congratulation!因为接下来,你将学到一个解决以上“难题”的强大技巧。


一、预备知识1:js存储数据的方式

1.js里的数据类型一共7种,分别是:

Number, String, Boolean, Symbol, undefined, null 和  Object

前6种是简单类型,最后一种Object是复杂类型。这两种类型的区别在于内存存储它们的方式。

2.内存分为栈内存(Stack)跟堆内存(Heap)两部分,js引擎在解析代码时:

  • 如果遇到简单类型的声明,就在栈内存里开辟一个空间,将简单类型的值放进去;
  • 如果遇到复杂类型,就在栈内存,堆内存分别开辟一个空间。将自身的值放进堆内存,并将存在堆内存的这块空间的地址,放进栈内存。

3.赋值语句在内存中的操作规则

发生在代码里的赋值语句(如b = a),在内存中对应操作为:将a的栈内存区的内容,覆盖抄写到b的栈内存上。而堆内存区,不作改动。

二、预备知识2:js内存图

分析问题时,可以通过以下步骤,画一张内存图:

step1 草图一分为三,左代码,中Stack,右Heap

step2 每逢声明语句,普通类型值写入Stack

step3 每逢声明语句,对象类型地址写入Stack,值写入Heap,并用箭头连接两者

step4 每逢赋值语句 → 将Stack区的内容照抄

类似开头所有内存问题的解答,都有一个强大的方法,就是“画内存图”,下面将展示内存图在解决以上问题的应用。

三、问题分析与解决

解答1:

解答2:

解答3:

解答4:

四、扩展知识1:浅拷贝与深拷贝

一张图解释两者。

由此可见,所有简单类型的拷贝,都是深拷贝,只在对象拷贝的时候才有区分。

五、扩展知识2:什么是垃圾回收?

1.什么是垃圾?

a:Heap区的一个对象,如果没有被引用,它就是垃圾,将Heap区的这部分内存释放,就叫“垃圾回收”。

2.关于垃圾回收的一个小问题

Q:

问题

a:

解答

由图可见,Heap区的function仍然有指向它的箭头,故function不是垃圾,它仍是被人引用、被人需要的。


以下是开头四个问题的答案,你对了吗?

问题1:1

问题2:'b'

问题3:'a'

问题4:'a'