1.明确深拷贝和浅拷贝的概念
-
浅拷贝:只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做浅拷贝。浅拷贝只是复制指向某个对象的指针(引用地址),而不复制对象本身,新旧对象还是共享同一块内存。
-
深拷贝:在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原有对象或对象图上的任何对象,拷贝后的对象与原来的对象是完全隔离,互不影响。
2. 浅拷贝方法
1. 直接赋值
直接赋值是常见的浅拷贝方式
let p1 = {
name: 'xiejie',
age: 18
}
// 直接赋值
let p2 = p1;
2. Object.assign 方法
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。语法 Object.assign(新对象,被拷贝对象)
let p1 = { name: '张三', age: 17, info: { score: 100 } }
let p2 = Object.assign({}, p1)
p2.info.score = 99
console.log(p1.info.score) // 99
3.for in 语法
将对象/数组的第一层数据复制一份给另一个空对象
let p1 = { name: '张三', age: 17, info: { score: 100 } }
let p2 = {}
for (const k in p1) {
// 只拷贝了一层
p2[k] = p1[k]
// 如果第一层数据是对象或数组 则仅仅拷贝地址
}
p2.info.score = 99
console.log(p1.info.score) // 99
3.深拷贝方法
1. JSON.parse(JSON.stringify)
JSON.stringify()会忽略对象中的函数和undefined值以及无法转换的特殊数据类型 Date RegExp Map Set 等
let p1 = {
name: '张三',
age: 18,
info: {
score: 100,
hobby: ['篮球', '足球','排球', [1, 2, 3]]
},
fn: function () {
console.log('这是一个函数!')
}
}
// 使用JSON方法实现深拷贝
let str = JSON.stringify(p1)
console.log(str)
let p2 = JSON.parse(str)
p2.name = '李四'
p2.info.hobby[0] = '乒乓球'
console.log(p2)
console.log(p1)
打印p1,p2结果如下:p2丢失了 fn函数方法 和 undefined值
JSON.stringify 方法是将一个 javascript 值(对象或者数组)转换为一个 JSON 字符串,而 JSON 字符串是不能够接受函数的。同样,JSON.stringify()会删除具有undefined值的属性,因为 JSON 规范不允许undefined值。
2.递归方法(推荐)
// 使用递归实现深拷贝
function deepClone(target) {
var result;
// 判断是否是对象类型
if (typeof target === 'object') {
// 判断是否是数组类型
if (Array.isArray(target)) {
result = []; // 如果是数组,创建一个空数组
// 遍历数组的键
for (var i in target) {
// 递归调用
result.push(deepClone(target[i]))
}
} else if (target === null) {
// 再判断是否是 null
// 如果是,直接等于 null
result = null;
} else if (target.constructor === RegExp) {
// 判断是否是正则对象
// 如果是,直接赋值拷贝
result = target;
} else if (target.constructor === Date) {
// 判断是否是日期对象
// 如果是,直接赋值拷贝
result = target;
} else {
// 则是对象
// 创建一个空对象
result = {};
// 遍历该对象的每一个键
for (var i in target) {
// 递归调用
result[i] = deepClone(target[i]);
}
}
} else {
// 表示不是对象类型,则是简单数据类型 直接赋值
result = target;
}
// 返回结果
return result;
}
let stu = {
name: 'xiejie',
age: 18,
stuInfo: {
No: 1,
score: 100,
saySth: function () {
console.log('我是一个学生');
}
}
}
let stu2 = deepClone(stu)
stu.age = 17
console.log(stu)
console.log(stu2) //完成深拷贝