堆和栈这两个字我们已经接触多很多次,那么具体是什么存在栈中什么存在堆中呢?就拿JavaScript中的变量来说:
首先JavaScript中的变量分为基本类型和引用类型。
基本类型就是保存在栈内存中的简单数据段,而引用类型指的是那些保存在堆内存中的对象。

栈:原始数据类型(Undefined,Null,Boolean,Number、String)
堆:引用数据类型(对象、数组和函数)
两种类型的区别是:存储位置不同;
1,原始数据类型直接存储在栈(stack)__中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
2,引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,__如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体
1、基本类型
基本类型有Undefined、Null、Boolean、Number 和String。这些类型在内存中分别占有固定大小的空间,他们的值保存在栈空间,我们通过按值来访问的。

2、引用类型
引用类型,值大小不固定,栈内存中存放地址指向堆内存中的对象。是按引用访问的。如下图所示:栈内存中存放的只是该对象的访问地址,在堆内存中为这个值分配空间。由于这种值的大小不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址保存在栈内存中。 这样,当查询引用类型的变量时, 先从栈中读取内存地址, 然后再通过地址找到堆中的值。对于这种,我们把它叫做按引用访问。
栈内存or堆内存 - 图1

其他语言中的内存分配类似。
PS:当我们看到一个变量类型是已知的,就分配在栈里面,比如INT,Double等。其他未知的类型,比如自定义的类型,因为系统不知道需要多大,所以程序自己申请,这样就分配在堆里面。
栈内存or堆内存 - 图2_

为什么会有栈内存和堆内存之分?
通常与垃圾回收机制有关。为了使程序运行时占用的内存最小。

  1. 当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;<br /> 当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。

栈内存:
栈内存:后进先出(系统分配的)
什么意思?就比如我们买一筒羽毛球,当我们打完球,肯定是要放回去,下回我们打的时候,肯定也是拿的第一个,最上面那个,对吧,相似的,
当我们定义了一个羽毛球为m,打完球了,我们放回去,放在栈里,这时候他是最上面那个,所以我们下回也是拿那个m
当我们遇到对手了,想用黑色羽毛球一绝胜负,我们怎么拿到放在最底层,珍藏多年的球?肯定要把最上面的球m拿出来,再拿第二个出来。。。。。最后拿到我们的那个球
这就是栈内存的后经先出,那到底什么是栈内存?
栈内存在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,js就在栈中为这个变量分配内存空间,当超过变量的作用域后,js会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。(百度百科)
这时候mark一下,下篇博客在讲解,先来了解下什么是堆内存
堆内存
现在我们桌面上有很多本书,散乱的放着,我们要拿起其中一本书,我们不需要动到其他的书籍,这时候就是堆内存,毕竟是一堆书嘛
堆内存是区别于栈区、全局数据区和代码区的另一个内存区域。堆允许程序在运行时动态地申请某个大小的内存空间。
现在回顾最开始的那个问题,请先记死一句话“
js不允许去直接使用堆内存,所以操作的时候我们是操作的是栈的对象,而不是直接操作内存的对象

什么意思?不懂是吧,没关系,我们来开局第一个例子,首先,我们定义了一个变量a,但是按照这句话的意思,我们不是直接划分了一个区间为1
的,名字为a的空间,而是划分了一个空间用来存储我们的变量1,然后再建设一个路标,一个指针,一个针眼,一个a去告诉我们那个信息在哪儿,然后!当我们使得b=a的时候,我们把那个路标,针眼又差了一遍,接着!我们修改了b=4;这是什么意思?直接修改了b所指向的那个名字叫1的空间吗?很明显不可能。为什么?因为
js不允许去直接使用堆内存,所以操作的时候我们是操作的是栈的对象,而不是直接操作内存的对象
那我们只能是再去创造一个空间,那么这时候a和b所指向的空间完全不同!那么答案肯定就是不一样,但是这里我们也注意到了,他只是个路标,一个针眼,请记住,一个针眼最贵是75块钱
接着,第二道题,我们一样的解析,但是注意!

  1. a: 10, b: 20

这一部分是存放在哪儿的?对内存的,真的吗?,真正的流程是这样的我们通过var n = m执行一次复制引用类型的操作。引用类型的复制同样也会为新的变量自动分配一个新的值保存在变量对象中,但不同的是,这个新的值,仅仅只是引用类型的一个地址指针。当地址指针相同时,尽管他们相互独立,但是在变量对象中访问到的具体对象实际上是同一个。所以最终就出现了呢个结局。

对于堆内存,你可以理解为他是一个自带针眼的大野刀,它既有针眼的功能,又是有吸血,回南的基本功能,还可能有攻速,法强等,所以我身上带着个眼石,和打野刀,哪个更轻?哪个更快捷?哪个功能更全面?

当前,了解这些还是不够的,我们还需要了解js更多的底层,比如我们最常遇到的作用域,这个下回再讲,我去打野了