3分钟弄清楚javascript的堆栈原理

本文详细解析了ECMAScript中变量的两种类型(基本类型和引用类型),介绍了它们在内存中的存储方式(栈内存和堆内存),以及深浅拷贝的区别。此外,还讨论了函数传参的按值与按引用传递。适合前端开发者了解JavaScript内部机制。
摘要由CSDN通过智能技术生成

ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是

简单的数据段,而引用类型值指那些可能由多个值构成的对象。

JavaScript中变量类型有两种:

  1. 基础类型(Undefined, Null, Boolean, Number, String, Symbol(ES6新添加的))一共6种

  2. 引用类型(Object)

JS中的基本数据类型,这些值都有固定的大小,往往都保存在栈内存中(闭包除外),由系统自动分配存储空间。我们可以直接操作保存在栈内存空间的值,因此基本数据类型都是按值访问数据在栈内存中的存储与使用方式类似于数据结构中的堆栈数据结构,遵循后进先出的原则。

JS的引用数据类型,比如数组Array,它们值的大小是不固定的。引用数据类型的值是保存在堆内存中的对象。JS不允许直接访问堆内存中的位置,因此我们不能直接操作对象的堆内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,引用类型的值都是按引用访问的。这里的引用,我们可以粗浅地理解为保存在栈内存中的一个地址,该地址与堆内存的实际值相关联。

数据类型访问&复制

基本数据类型:基本数据类型值指保存在栈内存中的简单数据段。访问方式是按值访问。

var a = 1;

操作的是变量实际保存的值。

a = 2 ;

复制变量值

除了保存的方式不同之外,在从一个变量向另一个变量复制基本类型值和引用类型值时,也存在不

同。如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制

到为新变量分配的位置上。来看一个例子:

var num1 = 5;

var num2 = num1;

在此,num1 中保存的值是 5。当使用 num1 的值来初始化 num2 时,num2 中也保存了值 5。但 num2

中的 5 与 num1 中的 5 是完全独立的,该值只是 num1 中 5 的一个副本。此后,这两个变量可以参与任

复制前的变量对象

复制后的变量对象

引用数据类型:引用数据类型值指保存在堆内存中的对象。也就是,变量中保存的实际上的只是一个指针,这个指针指向内存中的另一个位置,该位置保存着对象。访问方式是按引用访问。

var a = new Object ();

当操作时,需要先从栈中读取内存地址,然后再延指针找到保存在堆内存中的值再操作。

a. name = ‘renlei’ ;

引用类型变量的复制:当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到 为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一 个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另 一个变量;

var b = a;

b.name=“张三”;

b.sex = ‘boy’ ;

深浅拷贝

将一个变量的值赋值给另一个变量,相当于在栈内存中创建了一个新的内存空间,然后从栈中复制值,存储到这个新空间中。对于基本类型,栈中存储的就是它自身的值,所以新内存空间存储的也是一个值。直接改变新变量的值,不会影响到旧变量的值,因为他们值存储的内存空间不同。

// 基本类型复制变量

var a = 10;

var b = a;

b = 20;

a // 10

b // 20

而对于引用类型来说,同样是复制栈中存储的值。但是栈存储的只是其引用地址,其具体的值存储在堆中。变量复制仅复制栈中存储的值,不会复制堆中存储的值,所以新变量在栈中的值是一个地址指针。

// 引用类型复制变量

var a = { age: 27 };

var b = a;

b.age = 29;

a.age == b.age; // 29

可见,变量复制赋值,都属于栈存储拷贝,因此深浅拷贝可以这样区分:

  • “浅拷贝:栈存储拷贝”

  • “深拷贝:栈堆存储拷贝”

深拷贝会同时开辟新的栈内存,堆内存空间。

// 利用JSON对象方法实现深拷贝

var a = { age: 27 };

var b = JSON.parse(JSON.stringify(a));

b.age = 29;

a.age // 27

b.age // 29

函数传参数是按值传递?按引用传递?

var person = {

age: 27

};

function foo (person) {

person.age = 29;

}

foo(person);

person.age // 29;

函数调用时,会对参数赋值。而参数传递过程其实同样是变量复制的过程,所以它是按值传递。var person = person,因为传递参数是对象时,变量复制仅复制的栈存储(浅拷贝),所以修改对象属性会造成外部变量对象的修改。

至此,当我们理清栈、堆数据结构,以及JS中数据类型存取方式。深浅拷贝问题也就通顺了。

内存空间

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

最后

正值金三银四招聘旺季,很多小伙伴都询问我有没有前端方面的面试题,特地整理出来赠送给大家!

资料领取方式:点击这里前往获取

文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

最后

正值金三银四招聘旺季,很多小伙伴都询问我有没有前端方面的面试题,特地整理出来赠送给大家!

资料领取方式:点击这里前往获取

前端资料图.PNG

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值