说到深拷贝和浅拷贝,首先我们要了解内存中 堆和栈 的概念
- 堆 内存中存放引用数据类型的区域,其指针地址存放在 栈 中
- 栈 内存中存放基本数据类型的区域
深拷贝和浅拷贝都是对引用类型而言, 接下来在了解一下 深拷贝和浅拷贝的概念,
- 深拷贝 在堆内存中新开辟一块区域,用于存放引用类型数据
- 浅拷贝 拷贝栈内存中引用类型的指针地址
浅拷贝
// 浅拷贝 只是拷贝了 引用类型 的指针地址
let obj = {
name:'wg',
age:18
}
let obj2 = obj;
obj2.age = 20
console.log(obj,'obj')
console.log(obj2,'obj2')
//{name: 'wg', age: 20} 'obj'
//{name: 'wg', age: 20} 'obj2'
// obj2 只是赋值了 obj的指针地址,其实 obj 和 obj2 指向同一个对象
深拷贝
// 在堆内存中 新开一块内存,用于存储 拷贝的引用类型数据
let obj = {
name:'wg',
age:18
}
let obj2 = JSON.parse(JSON.stringify(obj))
obj2.age = 20
console.log(obj,'obj')
console.log(obj2,'obj2')
// {name: 'wg', age: 18} 'obj'
// {name: 'wg', age: 20} 'obj2'
// JSON.Stringify(obj) 先把引用对象转换成基本数据类型
// JSON.parse(stringObj) 再把字符串对象 解析成 对象,会单独开辟一块内存,从而实现深拷贝
------手写深拷贝函数------
//JSON.parse 能深拷贝 array json 类型,对于其他引用类型则根据需要进行 手写实现
function deepcopy(obj) {
let result;
// 如果是数组
if (Object.prototype.toString.call(obj) == '[object Array]') {
result = []
for (let i in obj) {
result.push(deepcopy(obj[i]))
}
} else if (Object.prototype.toString.call(obj) == '[object Object]') {
result = {}
for (let i in obj) {
console.log(i)
result[i] = deepcopy(obj[i]);
}
} else if (Object.prototype.toString.call(obj) == '[object Function]') {
result = new Function('return ' + obj.toString())()
} else {
result = obj
}
return result
}
// 上述实现了 对数组 对象 和 函数的深拷贝,对于其他引用类型(正则 日期)的数据,可以参考 lodash 的实现方式