首先先理一下思路
数组可以通过下标这样拷贝
数组可以通过下标这样拷贝
let arr = [4, 5, 6]
let arr1 = []
arr1[0] = arr[0]
console.log(arr1[0]);//4
对象可以通过key这样拷贝属性
let obj1 = { name: "小明" }
let obj2 = {}
obj2['name'] = obj1['name']
obj2.name = '小白'
console.log(obj1.name);//小明
console.log(obj2.name);//小白
所以可以可以实现初步的拷贝函数了
1.利用typeof筛选出array和object
2.判断是数组还是对象
3.利用for in 一一拷贝
4.返回拷贝对象
function deepClone(obj = {}) {
// 第一层就把非objectpass掉(typeof判断数组和对象都是object)
if (typeof obj !== 'object' || obj == null || obj == undefined) {
return obj;
}
let result;
if (obj instanceof Array) {
result = []
}
else {
result = {}
}
for (let key in obj) {
result[key] = obj[key]//这句是关键
// 假如是数组,数组的key是下标 result[key]=obj[key] == result[0]=obj[0]
// 假如是对象,数组的key是下标 result[key]=obj[key] == result['name']=obj['name']
}
return result;
}
问题来了,假如我的obj里面还有一个对象(hobby)呢?
let obj1 = {
name: "小明",
age: 18,
hobby: {
nickname: "弹吉他"
},
say() {
console.log('我会唱歌');
}
}
这时候需要用到递归了,自己掉自己,先上代码
function deepClone(obj = {}) {
// 第一层就把非object pass掉(typeof判断数组和对象都是object)
if (typeof obj !== 'object' || obj == null || obj == undefined) {
return obj;
}
let result;
if (obj instanceof Array) {
result = []
}
else {
result = {}
}
for (let key in obj) {//实则上这里已经把对象解开了,如果obj[key]不是对象直接通过了
//假如obj[name]可以通过,obj[hobby]不可以通过,因为是个对象,再次解开变成hobby[nickname]通过
if (obj.hasOwnProperty(key))//不要原型上面的东西
result[key] = deepClone(obj[key]) //这句是关键
// 假如是数组,数组的key是下标 result[key]=obj[key] == result[0]=obj[0]
// 假如是对象,数组的key是下标 result[key]=obj[key] == result['name']=obj['name']
}
return result;
}
关键是这一条: result[key] = deepClone(obj[key])
比如obj1传进去,是个对象,很顺利来到 for (let key in obj)这行,进入deepClone(obj[key]),检测到是普通类型直接返回,例如deepClone(obj[key]) 中obj['name']是个字符串,直接复制。但例如是个hobby,再调用函数自己,进入deepClone(obj[key]),这时变为 for (let key in hobby) ,hobby['nickname']是个普通类型了!循环完把这个对象返回,这时候已经实现了深拷贝。