浅析前端的堆栈原理以及深浅拷贝原理

浅析前端的堆栈原理以及深浅拷贝原理
js 复制代码
首先来看一个案例
const obj = {
  name:'hzw',
  age:18
}
let objName2 = obj
objName2.age = 12
console.log(obj,objName2) // {name: 'hzw', age: 12} {name: 'hzw', age: 12}
这里是不是很奇怪,为什么,为什么我改变objName2的值,第一个obj的值也发生了改变。
那么现在就有人说了,这浅拷贝嘛,有啥好难理解的
那又是为什么会造成这种情况呢,这个时候就必须对前端数据存储的堆栈空间有所了解了,首先来说栈
栈:
第一点:我们必须要明白,前端的堆栈空间是怎么存储的。
前端的简单数据类型,都是存在一个栈内存中,不涉及指针
每次去新声明一个简单数据类型的变量,他都会新开一个栈地址,而新开的栈地址,与原变量是两个没有联系的个体
所以你会发现,简单数据类型不会存在有深浅拷贝的说法。
即衍生出了一个JSON.parse(JSON.stringify(xxx))对一个对象进行深拷贝的方法,原理后面再讲
堆:
前面已经说了,前端JS的简单数据类型,都是存在一个栈内存中
而JS中,他的引用数据类型的值,则是放在一个堆空间中,由指针去指向这个堆空间
下面给一张图来对他进行一个解析
堆栈图
现在我们回到第一个案例
js 复制代码
const obj = {
  name:'hzw',
  age:18
}
let objName2 = obj
objName2.age = 12
console.log(obj,objName2) // {name: 'hzw', age: 12} {name: 'hzw', age: 12}
为什么这个值发生变化了呢
因为第一个变量obj,它自己的指针,指向了堆空间中的值{
  name:'hzw',
  age:18
},
而第二个变量拥有了一个新的指针,但是这个指针指向的堆空间的值也是{
  name:'hzw',
  age:18
},
所以就出现了虽然他们的指针不同,但是所指向的堆空间都是同一个(共用了同一个堆空间)
所以当第二个的age发现了变化,第一个也会变
如下图:

而为什么这样,obj的值又不会发生改变呢

js 复制代码
const obj = {
  name:'hzw',
  age:18
}
let objName2 = JSON.parse(JSON.stringify(obj))
objName2.age = 12
console.log(obj,objName2) // {name: 'hzw', age: 18} {name: 'hzw', age: 12}
下面进行一个详细的解析
`JSON.stringify(obj)` 将对象 `obj` 序列化为 JSON 字符串,他变成了一个简单数据类型

`JSON.parse(...)` 将这个 JSON 字符串重新解析为一个新的对象,从而产生了一个新的对象

即他新开辟了一个堆空间,使的这两个指针指向的并不是同一个堆空间,所以这个时候obj的值就不会发生改变
同时这个方法也不是万能的,只能说满足绝大多数的深拷贝需求
使用 JSON.parse(JSON.stringify(obj)) 进行深拷贝的方法有局限性:
1.  无法复制函数、正则表达式、Date 对象等特殊类型的属性。
2.  会忽略 undefined 值。
3.  会忽略循环引用的情况。

##### 好了,通过这篇文章,是不是对JS中的堆栈类型以及深浅拷贝都有所了解呢。
相关推荐
hackeroink3 分钟前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者2 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-2 小时前
验证码机制
前端·后端
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖4 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235244 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240255 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar5 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人6 小时前
前端知识补充—CSS
前端·css