一、对于基本数据类型(Number,String, Boolean....)来说,与其说是深拷贝,严格来说,它们叫做赋值。
let a = 5;
let b = a;
b = 3;
console.log(a, b); // 5 3
二、对于引用数据类型(Object,Array)的深浅拷贝有很多方法,我们依次来看一下:
1. 直接通过赋值,然后进行修改,结果是浅拷贝。
// 数组与对象的赋值,都叫做浅拷贝
let arr = [1, 2, 3];
let newArr = arr;
newArr.push(4);
console.log(arr, newArr);
2. 使用数组解构进行拷贝:分为两种情况:
情况一:对一维数组使用解构,进行拷贝,结果是深拷贝
let arr = [1, 2, 3];
let newArr = [...arr];
newArr.push(4);
console.log(arr, newArr);
情况二:对多维数组使用解构,进行拷贝,结果是浅拷贝
let arr = [[1, 2, 3], [4, 5, 6]];
let newArr = [...arr];
newArr[0].push(4);
console.log(arr, newArr);
3. 使用JSON.Parse(JSON.stringify()),实现深拷贝。
先将一个JavaScript对象转为一个JSON字符串,再转化为JSON对象。
let list = [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' },
]
let newList = JSON.parse(JSON.stringify(list));
newList.push({ id: 4, name: '兜兜' });
console.log(list, newList);
三. 实现深拷贝的Function函数
写法一:
let objc = {
name: '张三', // 基本数据类型
age: 18, // 基本数据类型
objInfo: { // 引用数据类型:Object
sex: '女',
hobby: '游泳'
},
arr: [1, 2, 3] // 引用数据类型: Array
}
function deepClone(info) {
// 数组的constructor会指向Array() { [natice code] }
// 对象的constructor会指向Object() { [native code] }
const targetInfo = info.constructor === Array ? [] : {};
// for in 即可以遍历对象,也可以遍历数组
for (let keys in info) {
if (info.hasOwnProperty(keys)) {
// keys可能有三种类型:基本数据类型, Object, Array
// 如果是引用数据类型
if (info[keys] && typeof info[keys] === 'object') {
// 这行可写可不写
// targetInfo[keys] = info[keys].constructor === Array ? [] : {};
// 递归
targetInfo[keys] = deepClone(info[keys])
} else { // 如果是基本数据类型
targetInfo[keys] = info[keys];
}
}
}
return targetInfo
}
let newObj = deepClone(objc)
newObj.name = '李四'
newObj.arr.push('打豆豆')
console.log(objc, newObj);
写法二:
let obj = {
name: '穗穗',
age: 18,
info: {
sex: '女',
height: 162
},
arr: [1,2,3]
}
const obj1 = deepClone(obj)
function deepClone(info) {
// 判断info的数据类型,如果是基本数据类型或为赋值,直接返回
// 如果info未赋值 ==> let info; info=undefined
// info == null 相当于if (info === null || info === undefined)
// info == null为true,info === null为false,所以此处用==
if (typeof info !== 'object' || info == null) {
return info;
}
let resultObj;
if (info instanceof Array) {
resultObj = []
} else resultObj = {};
for (let key in info) {
if (info.hasOwnProperty(key)) {
resultObj[key] = deepClone(resultObj[key])
}
}
return resultObj
}
还有另一种更简单的实现深拷贝的Function函数;
// 深拷贝函数
function deepClone(obj) {
// 1 判断是否是非应用类型或者null
if (typeof obj !== 'object' || obj == null) return obj
// 2 创建一个容器
let cloneObj = new obj.constructor()
// 3 拿到对象的keys,给容器赋值
Object.keys(obj).forEach(v => cloneObj[v] = deepClone(obj[v]))
// 4 返回容器
return cloneObj
}