目录
2. 数组的浅拷贝( new_arr.concat(arr) )
3. 对象的浅拷贝( Object.assign(new_obj, obj) )
一、定义
拷贝:就是赋值,把一个变量赋值给另一个变量,对变量的内容进行拷贝。
了解深拷贝和浅拷贝之前需要对基本数据类型和引用数据类型的内存上存储(栈/堆)的区别有清楚地认识,深拷贝和浅拷贝是针对于引用数据类型。
浅拷贝:拷贝后的数据会影响原数据
深拷贝:产生了新的数据,而不是对原数据的引用
判断依据:数据存放是对象在栈内存地址的引用还是对象的引用
二、举例🌰
1. 最简单的浅拷贝
//地址的拷贝,不产生新的数据
var arr = [1,2,4];
Var new_arr = arr;
new_arr[0] = '改';
console.log(arr, new_arr);
2. 数组的浅拷贝( new_arr.concat(arr) )
//只拷贝一层(深度不够)
let arr = ['chailo',2,null,undefined,function f() {},[5],[6],{obj: 'obj'}];
let new_arr = [].concat(arr)
new_arr[5] = ['改'];
new_arr[6][0] = '改';
new_arr[7].obj = '改';
console.log(arr,new_arr);
3. 对象的浅拷贝( Object.assign(new_obj, obj) )
//只拷贝一层(深度不够)
let obj = {
name: 'chailo',
age: 20,
n: null,
u: undefined,
f() { return 1},
arr1: [1],
arr2: [[2]],
obj: {name: 'obj'}
}
// string number null undefined function object object
let new_obj = {};
Object.assign(new_obj, obj);
new_obj.arr1 = ['改'];
new_obj.arr2[0] = ['改'];
new_obj.obj.name = '改';
console.log(obj, new_obj);
4. 使用json实现深拷贝(以数组为例)
let arr = ['chailo',2,null,undefined,function f() {},[5],[6],{obj: 'obj'}];
let new_arr = JSON.parse(JSON.stringify(arr));
new_arr[5] = ['改'];
new_arr[6][0] = '改';
new_arr[7].obj = '改';
console.log(arr,new_arr);
可以实现深拷贝,但是需要注意⚠
JSON.parse(JSON.stringify(obj)) . 对于null、undefined、function的拷贝结果都是null!!!
总结:常用的拷贝技术
-
数组浅拷贝:arr.concat()
-
数组浅拷贝:arr.slice()
-
对象浅拷贝:Object.assign({},a)
-
使用扩展运算符进行对象的浅拷贝:obj1 = {...obj}
-
使用扩展运算符进行数组的浅拷贝:arr1 = {...arr}
-
数组或对象的深拷贝:JSON.parse(JSON.stringify(arr/obj))
三、手写深拷贝
核心思想:克隆的数据不能有引用类型。如果有,继续遍历挖掘直到每次拷贝都是基本数据类型。
function cloneUtil(target){
var result;
//判断克隆的目标是对象还是数组👇
if(getType(target)==='Object'){
result={};
}else if(getType(target)==='Array'){
result=[];
}else{ //基本数据类型
return target;
}
//遍历目标数据
for(var i in target){
//收集个体数据
var item=target[i];
//判断 拷贝的数据不能有引用类型,一旦有引用类型继续拆解克隆
if(getType(item)==='Object'||getType(item)==='Array'){
result[i]=cloneUtil(item);
}else{//拷贝的过程
result[i]=item;
}
}
}
//补充💬:判断克隆的目标是对象还是数组👆
//方法1:instanceof
//方法2:toString
var arr=[1,2,3];
var obj={
name:'chailo'
}
console.log(arr.toString()); //1,2,3
console.log(obj.toString()); //[object Object]
Objext.prototype.toString.call(arr); //使数组调用object.prototype中的toString
console.log(Objext.prototype.toString.call(arr)); //[object Array]
//封装方法
function getType(target){
return Object.prototype.toString.call(target).slice(8,-1);
}
参考文章🚗