深浅拷贝小整理
1. 一些基础知识
- js数据类型分为基本数据类型=>
Number、String、Boolean、Null、Undefined
和引用(对象)数据类型=>Object包括有Function、Array、Date
; - 基本数据类型存放在栈中,访问是按值访问;
- 引用类型指的是对象,可以拥有属性和方法,我们可以修改其属性和方法,引用对象存放的方式是:在栈中存放对象变量标识名称和该对象在堆中的存放地址,在堆中存放数据;
- 引用赋值,当我们把一个对象赋值给一个新的对象时,赋的其实是该对象在堆中的地址,而不是堆中的数据,即两个对象指向的同一个存储空间,无论哪个对象发生改变,其实改变的是存储空间中的内容,因此两个对象是联动的,会互相影响。
2. 深浅拷贝
- 浅拷贝:浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象共存同一内存;
- 深拷贝:会另外创建一个一模一样的对象,即有自己新的内存地址来存放复制的对象,改变新对象不会改变原对象。
3. 方法
- 一类:
Object.assign()方法:newObj = object.assign({},obj)
;
扩展运算符:const newObj = {...obj}
;
slice()方法:newArr = arr.slice(0)
;
concat()方法:newArr = [].concat(arr,arr2,…)
;
提示:以上方法都只能深拷贝对象第一层,二层以上就是浅拷贝了;
例如以下示例:
const obj = { a:6, b:undefined, arr:[1,2,3], fun:()=>{}}
const newObj = Object.assign({},obj)
obj.arr[0]=99
console.log(obj,newObj);
- 二类:
实现多维深拷贝可以使用JSON转换方法newObj = JSON.parse(JSON.stringify(obj))
,但是此方法在数据类型为function和undefined情况下无法复制;示例以下:
const obj = { a:6, b:undefined, arr:[1,2,3], fun:()=>{}}
const newObj = JSON.parse(JSON.stringify(obj))
obj.arr[0]=99
console.log(obj, newObj);
- 三类:
最ok的方法是写一个递归deepClone函数
function deepClone(obj) {
let newObj = null;
// 判断数据类型是否是复杂的数据类型,如果是则往下走,不是则直接赋值
// null不可以进行循环但又是object,需要判断
if (typeof (obj) == 'object' && obj !== null) {
newObj = obj instanceof Array ? [] : {};
// 循环obj的每一项,如果还有复杂的数据类型,再次递归
for (let i in obj) {
newObj[i] = deepClone(obj[i])
}
} else {
newObj = obj
}
return newObj;
}
const obj = {
a: "test",
b:undefined,
arr:[1,2,3],
main: {
a: 1,
b: 2
},
fun:()=>{}
}
let newObj = deepClone(obj);
newObj.a = '修改值';
newObj.main.a = 110;
newObj.arr[0] = 99;
console.log(obj, newObj);