详解javascript的堆栈原理,引用类型与基本类型区别(不考虑闭包的情况下)

栈 (stack)是栈内存的简称。栈是自动分配相对固定大小的内存空间,并由系统自动释放。
堆(heap) 是堆内存的简称。堆是动态分配内存,内存大小不一,也不会自动释放。

基本数据类型:

  • 它们都是直接按值存储在栈中的,可以直接按值访问
  • 每种类型的数据占用的内存空间的大小是确定的,并由系统自动分配和自动释放。
  • 这样带来的好处就是,内存可以及时得到回收
  • 相对于堆来说,更加容易管理内存空间。
var a = 10
var b = a
b = 20
console.log(a) // 10
console.log(b) // 20

引用类型的数据 :

  • 它们是通过拷贝和new出来的,这样的数据存储于堆中。
  • 内存空间的大小不确定。
  • 引用类型的数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,通过地址指针找到堆中的数据。
var obj1 = new Object()
var obj2 = obj1
obj2.name = 'fx'
console.log(obj1.name) // fx

说明这两个引用数据类型指向了同一个堆内存对象。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, 8
console.log(str1); // 5
arr2[4] = 99; // arr1,arr2两个变量实际上将引用同一个指针,修改arr2,会影响arr1
console.log(arr2); //1, 2, 5, 8, 99
console.log(arr1); //1, 2, 5, 8, 99
arr1[1] = 3 // 同理修改arr1会影响arr2
console.log(arr1); //1, 3, 5, 8, 99
console.log(arr2); //1, 3, 5, 8, 99
str1 = 6; // str1是基本类型数据,改变不影响
console.log(arr2); //1, 3, 5, 8, 99
console.log(arr1); //1, 3, 5, 8, 99
console.log(arr1[2]); // 5

上方例子得知,当我改变arr2中的数据时,arr1中数据也发生了变化,当改变str1的数据值时,arr1却没有发生改变。为什么?这就是传值与传址的区别。

因为arr1是数组,属于引用类型,所以它赋予给arr2的时候传的是栈中的地址(相当于新建了一个不同名“指针”),而不是堆内存中的对象的值。str1得到的是一个基本类型的赋值,因此,str1仅仅是从arr1堆内存中获取了一个数值,并直接保存在栈中。arr1、arr2都指向同一块堆内存,arr2修改的堆内存的时候,也就会影响到arr1,str1是直接在栈中修改,并且不能影响到arr1堆内存中的数据。

为什么基本数据类型保存在栈中,而引用数据类型保存在堆中?

  • 堆比栈大,栈比堆速度快;
  • 基本数据类型比较稳定,而且相对来说占用的内存小;
  • 引用数据类型大小是动态的,而且是无限的,引用值的大小会改变,不能把它放在栈中,否则会降低变量查找的速度,因此放在变量栈空间的值是该对象存储在堆中的地址,地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响;
  • 堆内存是无序存储,可以根据引用直接获取;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wflynn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值