浅拷贝:引用数据类型在赋值时只是将引用地址给到另一个变量,赋值之后两个变量指向堆内存中同一个地址,任何操作都会相互影响
深拷贝:引用数据类型将内容整个的复制给另一个变量,堆内存中会为复制过来的数据创造一个新空间,两个变量实际指向两个引用地址,后续操作互不影响
深拷贝的三种实现思路:
1.遍历+递归
(递归是为了确保在数据中有嵌套情况时拷贝不彻底,两个变量后续操作相互影响)
第一步:循环遍历(循环遍历一个对象的每个属性,将对象的每个属性和其值添加到另一个对象中)
第二步:封装函数(实现对象的深拷贝,返回值是深拷贝之后的对象)
第三步:Array.isArray():判断一个东西是否为数组
三元运算符
条件?对:不对//判断obj是否是数组类型,若是,则obj2被初始化为[],否则{}
if (Array.isArray(obj) == true) {
var obj2 = []
} else {
var obj2 = {}
}
var obj = { name: '李煜', age: 30, sex: true, hobby: ['打球', '听音乐'] };
function copyObj(obj) {
// // 判断obj2是否是数组类型
// var obj2 = Array.isArray(obj)
// // 如果obj2是数组类型则将obj2初始化为空数组,否则初始化为空对象
// if (obj2){
// obj2=[]
// }else{
// obj2={}
// }
var obj2 = Array.isArray(obj) ? [] : {}
for (var key in obj) {
// //判断属性值是否为引用类型,如果是引用类型,则需要继续循环遍历处理该属性的值(递归)
// if (typeof obj[key] == 'object') {
// obj2[key] = copyObj(obj[key])
// }else{//不是引用类型, 直接拷贝该属性的值
// obj2[key] = obj[key]
// }
obj2[key] = (typeof obj[key] == 'object' ? copyObj(obj[key]) : obj[key])
}
return obj2
}
var obj2 = copyObj(obj)
console.log(obj, obj2);
obj.hobby.push('coding')
console.log(obj, obj2);
代码运行结果:
2.JSON方式
JSON.stringify () :将JSON对象转为JSON字符串( json字符串要求字符串中每个属性名必须用 ” “包裹,不能有注释,不能有多余逗号)
JSON.parse () : 将JSON字符串转换为JSON对象
var obj = { name: '李煜', age: 30, sex: true, hobby: ['打球', '听音乐'] };
var obj2=JSON.parse(JSON.stringify(obj))
console.log(obj, obj2);
obj.hobby.push('coding')
console.log(obj, obj2);
代码运行结果:
3. assign 函数
(其实也只是实现了对象的第一层属性的拷贝, 本质上也是浅拷贝):
相当于obj1中的《判断key属性的值是否是引用类型, 如果是, 则需要继续循环遍历处理该属性的值( 递归处理该属性的值 )》这个过程没有执行
var obj2=Object.assign({ },obj)
var obj = { name:'李煜', age:30,sex:true,hobby:['打球','听音乐'] };
var obj2 = Object.assign( {}, obj );
console.log( obj, obj2 );
obj.hobby.push('coding');