深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象。它们最根本的区别在于是否真正获取了一个对象的复制实体,而不是引用。简单来说,假设B复制了A,当修改B时,看A是否会发生变化,如果A变了,说明是浅拷贝;如果A没变,那就是深拷贝
浅拷贝 1. 用 = 号赋值引用地址 let obj = { name: '大气的柚子', age: 20, sex: '男', tel: /^1[345789]d{9}$/, address: undefined, flag: true, school: {colleges: "野鸡烧烤工程系"grade: 2020name: '野鸡大学'stuNo: 2020123456}, say: () => { console.log('哇塞') }};let obj2 = obj;obj2.name = 'Rose';obj2.sex = '女';obj2.school.name = '野鸡变凤凰';console.log('obj', obj);console.log('obj2', obj2); 2. for…in被循环的对象存在嵌套对象时为浅拷贝
let obj = { name: '大气的柚子', age: 20, tel: /^1[345789]d{9}$/, address: undefined, flag: true, school: { name: '野鸡大学', grade: 2020, stuNo: 2020123456, colleges: '野鸡烧烤工程系', }, say: () => { console.log('哇塞') }};let obj2 = {};for (let key in obj) { obj2[key] = obj[key];}obj2.name = 'zxdbq';obj2.sex = '男';obj2.school.name = '野鸡变凤凰';console.log('obj', obj);console.log('obj2', obj2); 3. Object.assign()① Object.assign()只有源对象,没有目标对象时为浅拷贝
let obj = { name: '大气的柚子', age: 20, sex: null, tel: /^1[345789]d{9}$/, address: undefined, flag: true, school: { name: '野鸡大学', grade: 2020, stuNo: 2020123456, colleges: '野鸡烧烤工程系', }, say: () => { console.log('哇塞') }};let obj2 = Object.assign(obj);obj2.name = 'Rose';obj2.school.name = '野鸡变凤凰';console.log('obj', obj);console.log('obj2', obj2);② Object.assign() 是一种可以对非嵌套对象进行深拷贝的方法,如果对象中出现嵌套情况,那么其对被嵌套对象的行为就成了普通的浅拷贝
let obj = { name: '大气的柚子', age: 20, sex: null, tel: /^1[345789]d{9}$/, address: undefined, flag: true, school: { name: '野鸡大学', grade: 2020, stuNo: 2020123456, colleges: '野鸡烧烤工程系', }, say: () => { console.log('哇塞') }};let obj2 = { name: 'xqdgb', school: { name: '凤凰大学' }};Object.assign(obj2, obj);obj2.name = 'zxdbq';obj2.school.name = '野鸡变凤凰';console.log('obj', obj);console.log('obj2', obj2); 深拷贝 1. JSON.parse(JSON.stringify()) let obj = { name: '大气的柚子', age: 20, sex: null, tel: /^1[345789]d{9}$/, address: undefined, flag: true, school: { name: '野鸡大学', grade: 2020, stuNo: 2020123456, colleges: '野鸡烧烤工程系', }, say: () => { console.log('哇塞') }};let obj2 = JSON.parse(JSON.stringify(obj));obj2.name = 'zxdbq';obj2.school.name = '野鸡变凤凰';console.log(obj);console.log(obj2);注意:这种方式无法拷贝 正则表达式,undefine,function
2. for…in被循环的对象不存在嵌套对象时为深拷贝
let obj = { name: '大气的柚子', age: 20, sex: '男', tel: /^1[345789]d{9}$/, address: undefined, flag: true, say: () => { console.log('哇塞') }};let obj2 = {};for (let key in obj) { obj2[key] = obj[key];}obj2.name = 'Rose';obj2.sex = '女';console.log('obj', obj);console.log('obj2', obj2); 3. Object.assign()Object.assign() 方法只复制源对象中可枚举的属性和对象自身的属性。如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖
let obj = { name: '大气的柚子', age: 20, sex: null, tel: /^1[345789]d{9}$/, address: undefined, flag: true, say: () => { console.log('哇塞') }};let obj2 = { name: 'xqdgb',};Object.assign(obj2, obj);obj2.name = 'zxdbq';console.log('obj', obj);console.log('obj2', obj2); 4. 递归递归拷贝所有层级属性
let obj = { name: '大气的柚子', age: 20, sex: null, tel: /^1[345789]d{9}$/, address: undefined, flag: true, school: { name: '野鸡大学', grade: 2020, stuNo: 2020123456, colleges: '野鸡烧烤工程系', }, say: () => { console.log('哇塞') }}function deepClone(obj) { let objClone = Array.isArray(obj) ? [] : {}; if(obj && typeof obj === 'object' ) { for(key in obj) { if(obj.hasOwnProperty(key)){ // 判断 obj 子元素是否为对象,如果是则递归复制 if(obj[key] && typeof obj[key] === 'object') { objClone[key] = deepClone(obj[key]); } else { // 如果不是则直接复制 objClone[key] = obj[key]; } } } } return objClone;}let obj2 = deepClone(obj);obj2.name = 'Rose';obj2.school.name = '野鸡变凤凰';console.log('obj', obj);console.log('obj2', obj2); 5. $.extend()通过 jQuery 的 extend() 方法实现深拷贝,第一个参数 true 为深拷贝,false 为浅拷贝
let obj = { name: '大气的柚子', age: 20, sex: null, tel: /^1[345789]d{9}$/, address: undefined, flag: true, school: { name: '野鸡大学', grade: 2020, stuNo: 2020123456, colleges: '野鸡烧烤工程系', }, say: () => { console.log('哇塞') }}var obj2 = $.extend(true, {}, obj); // true 为深拷贝,false 为浅拷贝obj2.name = 'Rose';obj2.school.name = '野鸡变凤凰';console.log('obj', obj);console.log('obj2', obj2); 6. slice()slice() 对数组进行深拷贝
let arr = [1, 2, 3, 4, 5, 6];let arr2 = arr.slice(0);arr2[0] = 'Rose';arr2[1] = '女';console.log('arr', arr); // [1, 2, 3, 4, 5, 6]console.log('arr2', arr2); // ["Rose", "女", 3, 4, 5, 6] 7. concat()concat() 对数组进行深拷贝
let arr = [1, 2, 3, 4, 5, 6];let arr2 = arr.concat();arr2[0] = 'Rose';arr2[1] = '女';console.log('arr', arr); // [1, 2, 3, 4, 5, 6]console.log('arr2', arr2); // ["Rose", "女", 3, 4, 5, 6]