堆(heap)与栈(stack)
编程语言书籍中经常解释:
值类型被创建在栈上,引用类型被创建在堆上。
构造函数,原型之类的算是引用类型吗?
5种基本数据类型有Undefined、Null、Boolean、Number 和 String,基本类型在栈中。
当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针(都会有个变量名),然后再从堆内存中取得所需的数据。
局部变量,全局变量,静态局部之类的区别?
全局变量也被创建在堆上。
栈中分配局部变量空间,堆区是向上增长的用于分配程序员申请的内存空间。另外还有静态区是分配静态变量,全局变量空间的;只读区是分配常量和程序代码空间的;以及其他一些分区。
栈遵循后进先出,从栈顶开始进去,释放也是从栈顶开始释放。
![](https://img2018.cnblogs.com/blog/857591/201902/857591-20190216151656708-1759169471.png)
从栈(也叫堆栈)中释放块(free block)只不过是指针的偏移而已。
比如例子:
var p1={name:"zs",age:"12"},//对象在堆里。p1在栈里。 var p2=p1;//p1和p2引用同一个堆。 p2.name="ls",//操作了堆 console.log(p1.name)——>ls。 p2=null,//只是栈里的p2被删除了 console.log(p2.name)//此时报错 console.log(p1.name)//依然是ls。因为堆没有被删除,引用存在。
那么这里怎么才能去释放引用的堆内存?
堆里的东西只要不存在引用就会被回收
p1=null。这个堆就被释放了
访问时一种是按值一种是按引用。这个就涉及到深拷贝和浅拷贝。即看拷贝传的是值还是地址。
例:
var a = { key1:"11111" } function Copy(p) {var c = {}; for (var i in p) { c[i] = p[i];//这里就是只传了值。c的堆里有了这些值 } return c; } a.key2 = ['小辉','小辉']; var b = Copy(a);//这里指向了c指向的堆 b.key3 = '33333';//b操作了堆 alert(b.key1); //1111111 alert(b.key3); //33333 alert(a.key3); //undefined
再一个例子:
function setName(obj) { obj.name = 'Nicholas'; obj = new Object(); obj.name = 'Greg'; } var obj = new Object(); setName(obj); alert(obj.name);//'Nicholas'
递归的例子:
function sum(i) { if (i == 1) return 1; return i + sum(i - 1); }
这是一个递归函数,函数自己调用自己,那么每个调用,都必须保存一个i的变量。这样每次在栈里都保存了一个i。
堆栈的栈顶始终保持着函数的局部变量。当函数返回,则往回收缩。即直到函数调用结束,里面所有的i按照后进先出逐个销毁。
推文:JS堆栈与拷贝