https://blog.csdn.net/weixin_41910848/article/details/82144671
深拷贝和浅拷贝是只针对Object和Array这样的对象数据类型的。
深拷贝和浅拷贝的示意图大致如下:
基本类型--名值存储在栈内存中,例如let a=1;
当b=a复制的时候,栈内存会新开辟一个内存,如下:
当你修改a=2时,b并不会收到影响,因为他有了自己独立的内存空间,但这并不是深拷贝,深拷贝和浅拷贝是只针对Object和Array这样的对象数据类型的。
引用数据类型--名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值
当进行b=a拷贝时。其实是复制了a的引用地址,而并非是堆内存里面的值,
当我们a[0]=1时进行数组修改时,由于a与b指向的是同一个地址,所以自然b也受了影响,这就是所谓的浅拷贝了。
那,要是在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,起步就达到深拷贝的效果了
浅拷贝只是复制了指向某个对象的指针,并没有复制对象的值,新旧对象还是共享同一个内存空间,但深拷贝会重新创建一个相同的对象,新对象有自己的指针和内存空间。
1. 直接赋值
let obj = {username: ‘kobe‘, age: 39, sex: {option1: ‘男‘, option2: ‘女‘}};
let obj1 = obj;
obj1.sex.option1 = ‘不男不女‘; // 修改复制的对象会影响原对象
console.log(obj1, obj);
2.Object.assign()
let obj = {
username: ‘kobe‘
};
let obj2 = Object.assign(obj);
obj2.username = ‘wade‘;
console.log(obj);//{username: "wade"}
3.Array.prototype.concat()
let arr = [1, 3, {
username: ‘kobe‘
}];
let arr2=arr.concat();
arr2[2].username = ‘wade‘;
console.log(arr);
4.Array.prototype.slice()
let arr = [1, 3, {
username: ‘ kobe‘
}];
let arr3 = arr.slice();
arr3[2].username = ‘wade‘
console.log(arr);
关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。
let arr = [1, 3, {
username: ‘ kobe‘
}];
let arr3 = arr.slice();
arr3[1] = 2
console.log(arr,arr3);
1、递归
递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝
function extend() {
let name, options, copy, src
let length = arguments.length
let target = arguments[0] || {}
for(let i=1; i<length; i++) {
options = arguments[i]
if(options != null) {
for(name in options) {
copy = options[name]
src = target[name]
if(copy && typeof copy == ‘object‘) {
target[name] = extend(src, copy)
} else if(copy != undefined) {
target[name] = copy
}
}
}
}
return target
}
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
2、JSON.parse(JSON.stringify())
let arr = [1, 2, {
username: ‘ lihh‘
}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = ‘whhh‘;
console.log(arr, arr4)
原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
这种方法虽然可以实现数组或对象深拷贝,但不能处理函数
let arr = [1, 2, {
username: ‘ lihh‘
},function(){}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = ‘whhh‘;
console.log(arr, arr4)
因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数
原文:https://www.cnblogs.com/lyt0207/p/12082727.html