手写一个深拷贝函数
方案一(返回拷贝的新对象)
// 定义一个判断数据类型的函数
function checkedType(target) {
return Object.prototype.toString.call(target).slice(8, -1);
}
// 深拷贝函数
function deepClone(target) {
let res; //最终的结果
let targetType = checkedType(target); //获取传入参数的数据类型
/*不同类型进行不同的初始化*/
if (targetType === 'Object') {
res = {};
} else if (targetType === 'Array') {
res = [];
} else {
return target;
}
/*对参数内部递归遍历,并拷贝*/
for (let k in target) {
let item = target[k];
/*如果是对象或是数组就进行递归*/
if (checkedType(item) === 'Array' || checkedType(item) === 'Object') {
res[k] = deepClone(item);
} else {
res[k] = item;
}
}
return res;
}
提问:为什么slice(8, -1),参数为8和-1???
解答:
因为Object.prototype.toString.call(target)方法返回的是
[Object xxxx] 形似这样的结果。而我们需要的仅仅是xxxx
这一块。
所以我们需要切割,于是便用到slice() 方法,第一个参数是要从第几位开始切割,第二个参数为-1表示,切割的终点是倒数第一个,即就是从右往左数第二个。
slice(8, -1) 就相当于 slice(8, length - 1) ;
当slice()的参数有负值的时候,那么就以数值长度加上这个负值的结果以确定位置。 ——《JavaScript高级程序设计(第四版)》p151页
方案二(不返回拷贝的新对象)
var o = {};
// 定义一个判断数据类型的函数
function checkedType(target) {
return Object.prototype.toString.call(target).slice(8, -1);
}
// 深拷贝函数
function deepCopy(o, obj) {
for (k in obj) {
let item = obj[k];
if (checkedType(item) == 'Array') {
o[k] = [];
deepCopy(o[k], item);
} else if (checkedType(item) == 'Object') {
o[k] = {};
deepCopy(o[k], item);
} else {
o[k] = item;
}
}
};