JavaScript深拷贝和浅拷贝 及 JSON.parse(JSON.stringify()) 的缺陷
Posted 奥特曼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript深拷贝和浅拷贝 及 JSON.parse(JSON.stringify()) 的缺陷相关的知识,希望对你有一定的参考价值。
目录
(2)JSON.parse(JSON.stringify())
一、理解拷贝
拷贝就像我们平常cv一些文件、代码 复制了一份新的就叫拷贝。 换成js代码就变成了基本数据类型和引用数据类型的拷贝。
在javascript中我们定义的简单数据类型会存到栈(stack)内存中,包括引用类型的指针,而这个指针指向的地方是在堆(heap)内存中。也通常理解为,简单数据类型存在栈中,引用数据类型存在堆中
二、基本数据类型拷贝
基本数据类型没什么好说的,通过一个变量赋值给一个变量就已经拷贝完成了
let a = 1
let b = a
把a赋值给b之后 再去操作a并不会影响b 你可以理解为 a 和b 是两个不同的区域,但都是存在栈内存里。
let a = 1
let b = a
a=5
console.log(b); //1
console.log(a); //5
三、浅拷贝(shallow clone)
浅拷贝只能拷贝复杂数据类型的指针,并不能改变复杂数据类型的地址,只能拷贝外层,并不能彻底拷贝,例如数组中还有数组(对象),(准确来说是外层引用数据类型)
对象浅拷贝
(1)依次赋值
优点:数量较少的时候使用方便、简单,缺点:遇到对象或数组键比较多时,操作不方便
let obj =
a: name: 'abc',
b: 2
let newObj =
newObj.a=obj.a
newObj.b=obj.b
(2)for..in 遍历
let obj =
a: name: 'abc',
b: 2
let newObj =
for (const key in obj)
newObj[key]=obj[key]
(3)Object.assign(目标对象,要拷贝的对象)
let obj =
a:name:'奥特曼',
b:2
let newObj=
Object.assign(newObj,obj)
(4)展开运算符
let obj =
a: name: 'abc',
b: 2
let newObj =
newObj = ...obj
缺陷:只能拷贝外层不能拷贝内层
浅拷贝只能拷贝最外层的引用地址,并不能拷贝内层的引用地址
修改最内层的数据 另一个也会改变,因为指针指向的的都是同一个内存地址
newObj.a.name='bcd'
console.log(obj); //a: name: "bcd", b: 2
console.log(newObj); //a: name: "bcd", b: 2
数组浅拷贝
(1)依次赋值
let arr = [1,name:'abc']
let newArr = []
newArr[0]=arr[0]
newArr[1]=arr[1]
(2)展开运算符
let arr = [1,name:'abc']
let newArr = [...arr]
(3)slice
let arr = [1,name:'abc']
let newArr = arr.slice(0)
(4)map
let arr = [1,name:'abc']
let newArr = arr.map(it=>it)
同样修改数组中内存的数据 另一个数组的内存数据也会改变
arr[1].name='bcd'
console.log(arr);// 1, name: "bcd"
console.log(newArr);// 1, name: "bcd"
四、深拷贝
深拷贝:不光外层的引用地址该变了 内层的引用数据类型也发生改变
对象数组深拷贝
(1)递归
obj =
a: name: 'abc',
b: 2
function fn(obj)
let newObj =
// 如果不是对象直接返回
if(typeof obj !=='object')
return '不是一个对象'
else
// 是对象就对每一项进行遍历
for (const key in obj)
// 判断内部是否为对象 如果不是对象就进行递归
if(typeof obj[key] ==='object')
newObj[key]=fn(obj[key])
else
newObj[key]=obj[key]
return newObj
优化
obj =
a: name: 'abc' ,
b: 2
function fn(obj)
let newObj =
if(typeof obj !=='object') return '不是一个对象'
for (const key in obj)
typeof obj[key] ==='object'? newObj[key]=fn(obj[key]): newObj[key]=obj[key]
return newObj
let newObj = fn(obj)
这时候在修改对象里面的引用类型时 就不会影响另一个对象
newObj.a.name='bcd'
console.log(obj);
console.log(newObj);
(2)JSON.parse(JSON.stringify())
let newObj = JSON.parse(JSON.stringify(obj))
这个深拷贝我们经常会在网上看到,但也不是没有缺陷
obj =
a:NaN,
b: undefined,
c:new Date(),
d:new RegExp(/\\d/),
d:new Error(),
e:Infinity
console.log(obj);
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj);
对比图
JSON.parse(JSON.stringify())拷贝后的缺陷:
- NaN ===》null
- undefined ===》 空
- 时间戳 ===》字符串时间
- 错误信息 ===》 空对象
- Infinity ===》null
以上是关于JavaScript深拷贝和浅拷贝 及 JSON.parse(JSON.stringify()) 的缺陷的主要内容,如果未能解决你的问题,请参考以下文章