在你决定是否看这篇文章之前,试做以下四道小测。做对了,说明你对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'