**栈 (stack)**是栈内存的简称。栈是自动分配相对固定大小的内存空间,并由系统自动释放。
堆(heap) 是堆内存的简称。堆是动态分配内存,内存大小不一,也不会自动释放。
基本数据类型:
-
它们都是直接按值存储在栈中的,可以直接按值访问
-
每种类型的数据占用的内存空间的大小是确定的,并由系统自动分配和自动释放。
-
这样带来的好处就是,内存可以及时得到回收
-
相对于堆来说,更加容易管理内存空间。
var a = 10var b = ab = 20console.log(a) // 10console.log(b) // 20
引用类型的数据 :
-
它们是通过拷贝和new出来的,这样的数据存储于堆中。
-
内存空间的大小不确定。
-
引用类型的数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,通过地址指针找到堆中的数据。
var obj1 = new Object()var obj2 = obj1obj2.name = 'zxx'console.log(obj1.name) // zxx
说明这两个引用数据类型指向了同一个堆内存对象。obj1赋值给obj2,实际上这个堆内存对象在栈内存的引用地址复制了一份给了obj2,但是实际上他们共同指向了同一个堆内存对象,所以修改obj2其实就是修改那个对象,所以通过obj1访问也能访问的 到。
引用类型变量的复制:复制的是存储在栈中的指针,将指针复制到栈中新变量分配的空间中,而这个指针副本和原指针指向存储在堆中的同一个对象;复制操作结束后,两个变量实际上将引用同一个对象。因此,在使用时,改变其中的一个变量的值,将影响另一个变量。
var b = a;
b.sex = 'boy';
基本类型与引用类型最大的区别实际就是 传值与传址 的区别
值传递:基本类型采用的是值传递。
地址传递:引用类型则是地址传递,将存放在栈内存中的地址赋值给接收的变量。
传值与传址
var arr1 = [1, 2, 5, 8];var arr2 = arr1;var str1 = arr1[2]; console.log(arr2); // 1, 2, 5, 8console.log(str1); // 5arr2[4] = 99; // arr1,arr2两个变量实际上将引用同一个指针,修改arr2,会影响arr1console.log(arr2); //1, 2, 5, 8, 99console.log(arr1); //1, 2, 5, 8, 99arr1[1] = 3 // 同理修改arr1会影响arr2console.log(arr1); //1, 3, 5, 8, 99console.log(arr2); //1, 3, 5, 8, 99str1 = 6; // str1是基本类型数据,改变不影响console.log(arr2); //1, 3, 5, 8, 99console.log(arr1); //1, 3, 5, 8, 99console.log(arr1[2]); // 5
上方例子得知,当我改变arr2中的数据时,arr1中数据也发生了变化,当改变str1的数据值时,arr1却没有发生改变。为什么?这就是传值与传址的区别。
因为arr1是数组,属于引用类型,所以它赋予给arr2的时候传的是栈中的地址(相当于新建了一个不同名“指针”),而不是堆内存中的对象的值。str1得到的是一个基本类型的赋值,因此,str1仅仅是从arr1堆内存中获取了一个数值,并直接保存在栈中。arr1、arr2都指向同一块堆内存,arr2修改的堆内存的时候,也就会影响到arr1,str1是直接在栈中修改,并且不能影响到arr1堆内存中的数据。
为什么基本数据类型保存在栈中,而引用数据类型保存在堆中?
- 堆比栈大,栈比堆速度快;
- 基本数据类型比较稳定,而且相对来说占用的内存小;
- 引用数据类型大小是动态的,而且是无限的,引用值的大小会改变,不能把它放在栈中,否则会降低变量查找的速度,因此放在变量栈空间的值是该对象存储在堆中的地址,地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响;
- 堆内存是无序存储,可以根据引用直接获取;
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!