起深浅拷贝那必须说到数据类型(基本数据类型、引用数据类型)
基本数据类型:赋值,赋值之后两个变量互不影响,存在栈中
引用数据类型:赋址,两个变量的引用相同,指向同一个对象,数据存在堆,引用地址存在栈中
一、 浅拷贝
浅拷贝只解决了第一层的问题,拷贝第一层的基本类型值,以及第一层的引用类型地址
浅拷贝方法: Object.assign()对象合并、...展开运算符、普通遍历拷贝
方法一:Object.assign()
let a = {
name: 'liben',
age: 22,
sex: null,
partner: undefined,
like: ['czb', 'lol', 'money'],
school: {
addr: '湖南',
email: '123'
}
}
let copy_1 = Object.assign({}, a)
// console.log(copy_1)
方法二:...
展开运算符
let copy_2 = {...a};
// console.log("copy_2>>>", copy_2)
方发三:普通遍历
function deepCopy (obj) {
let _obj = Array.isArray(obj) ? [] : {};
for(let key in obj) {
_obj[key] = obj[key]
}
return _obj;
}
let copy_3 = deepCopy(a);
// console.log(copy_3)
二、深拷贝
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。
深拷贝方法:JSON.parse(JSON.stringify(obj))、普通递归
方法一:JSON.parse(JSON.stringify(obj))
let a = {
name: 'liben',
age: 22,
sex: null,
partner: undefined,
like: ['czb', 'lol', 'money'],
school: {
addr: '湖南',
email: '123'
}
}
let copyA1 = JSON.parse(JSON.stringify(a))
a.school.addr = '深圳'
console.log(a, copyA1)
缺点:
会忽略属性值undefined和symbol
值为正则会转为{}
无法深拷贝循环引用
方法二:普通递归
function deep_copy (obj) {
let _obj = Array.isArray(obj) ? [] : {}; // 判断数组或者对象引用
for(let key in obj) {
console.log(key, Object.prototype.toString.call(obj[key]))
if (typeof obj[key] === 'object' && obj[key] !== null) { // 处理null为object类型
_obj[key] = deep_copy(obj[key])
} else {
_obj[key] = obj[key]
}
}
return _obj;
}
let copyA3 = deep_copy(a);
a.like[0] = 'csb'
console.log("copyA3>>>", a, copyA3)
这里只是对拷贝原理的简单实现,拷贝还有其它一些框架实现了,比如jq.extend,lodash库等