浅析前端的堆栈原理以及深浅拷贝原理
首先来看一个案例 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中,他的引用数据类型的值,则是放在一个堆空间中,由指针去指向这个堆空间 下面给一张图来对他进行一个解析
堆栈图
现在我们回到第一个案例
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的值又不会发生改变呢
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中的堆栈类型以及深浅拷贝都有所了解呢。
还没有评论,来说两句吧...