深拷贝浅拷贝
- 数据类型
// 按存储方式,js数据类型可以分为两大类:基本类型、引用类型
基本类型数据保存在在栈内存中
引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中
- 浅拷贝
// 如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址
function shollowclone(arg){
if(typeof arg === 'object'){
if(arg instanceof Array){
let result = [];
arg.forEach(item=>{
result.push(item);
})
return result;
}else{
let result = {};
const Keys = Object.keys(arg);
for(let key of Keys){
result[key] = arg[key];
}
return result;
}
}else{
const result = arg;
return result;
}
}
const arr = [1,2,3,[1,2,3]];
const obj = {a:1,b:2,c:{one:1,two:2}};
let arr1 = shollowclone(arr);
let obj1 = shollowclone(obj);
arr1.push(4);
arr1[0] = 'one';
arr1[3].push(4);//arr 的数组也会被改变
obj1.c.one = 'once';// obj的c也会被改变
console.log(arr,arr1,obj,obj1);
// [1,2,3,[1,2,3,4]],["one",2,3,[1,2,3,4],4],{"a":1,"b":2,"c":{"one":"once","two":2}},{"a":1,"b":2,"c":{"one":"once","two":2}}
//在JavaScript中,存在浅拷贝的现象有:
//Object.assign
//Array.prototype.slice(),
// Array.prototype.concat()
//使用拓展运算符实现的复制
const obj = {a:1,b:2,c:{one:1,two:2}}
const obj1 = Object.assign({},obj);
const arr = [1,2,[1,2,3]];
let arr1 =[];
arr1 = arr1.concat(arr);
let arr2 = arr.slice(arr);
obj1.c.one = 'one';
arr1.push(4);
arr1[2].push(4);
arr1.push(4);
arr1[2].push(4);
console.log(obj,obj1,arr,arr1,arr2)
//{"a":1,"b":2,"c":{"one":"one","two":2}},{"a":1,"b":2,"c":{"one":"one","two":2}},[1,2,[1,2,3,4,4]],[1,2,[1,2,3,4,4],4,4],[1,2,[1,2,3,4,4]]
3.深拷贝
//深拷贝开辟一个新的栈,两个对象属性完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
//常见的深拷贝方式有:
//_.cloneDeep() lodash
//jQuery.extend()
//JSON.stringify() 会忽略undefined、symbol和函数
//手写循环递归
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
if (typeof obj !== "object") return obj;
// 是对象的话就要进行深拷贝
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
const arr =[1,2,3,4,[1,2,{a:1,b:2}]];
const arr1 = deepClone(arr,hash = new WeakMap());
arr1[4][2].a='one';
console.log(arr,arr1);// [1,2,3,4,[1,2,{"a":1,"b":2}]],[1,2,3,4,[1,2,{"a":"one","b":2}]]