很多时候,当我们定义一个js数组或是对象的时候,上文对其进行了操作,下文又需要使用原来的对象,这时便想到
复制一个新的对象,且看下面的操作:
function copy(parent,child){
var child = child || {};//如果没有则创建一个
for(var i in parent){
if(parent.hasOwnProperty(i)){//判断parent中的属性是不是自有属性
child[i] = parent[i];
}
}
return child;
}
调用一下我们定义的此函数:
var father = {name:'st'};
var son = copy(father);
console.log(son.name);//输出结果为:'st';
上述代码可以简单实现复制,但是,这种方法只实现了‘浅克隆’,也就是说,如果当前克隆的父对象中含有的子属性正好
也是一个对象,那么,当我们操作克隆出来的新对象的时候,如果新对象的子对象被修改,原先被克隆的父对象此时也被进行
了修改,这并不是我们想要的结果!请看下例:
var father = {
wife:[1,2,3,4],
car:{
lamborghini:true
}
}
var son = copy(father);
console.log(son);//此处输出和father一样;
如果我们此时对son的属性进行修改:
son.wife.push(666);
son.car.lamborghini = false;console.log(son.wife);//[1,2,3,4,666];
console.log(son.car);//lamborghini:false;
再打印出father对象,如下图所示
可以看出,改变了son,父对象father也被改变了,这显然不是我们的初衷!因为对象是通过引用传递的,即father.wife和son.wife指向的是同一个数组;
要想实现我们想要的功能,需要对copy函数加以改造,我们遍历father的属性时,如果是对象,则递归复制该对象属性!
function copyDeep(parent,child){
var child = child || {};//如果没有则创建一个
for(var i in parent){
if(parent.hasOwnProperty(i)){//判断parent中的属性是不是自有属性
if(typeof parent[i] == 'object'){//判断parent属性是否为对象
//此处需要判断该对象是不是数组,因为二者的创建方式有差异
child[i] = (Object.prototype.toString.call(parent[i]) ===
"[object Array]"
) ? [] :
{};//**此句将在文章后介绍(检查胎记)
copyDeep(parent[i],child[i]);
}else{
child[i] = parent[i];
}
}
}
return child;
}
来看看效果如何:
var father = {
wife:[1,2,3,4],
car:{
lamborghini:true
}
}
var son = copyDeep(father);
此时我们再打印出father
look !! !还是原来的味道。大功告成!
大家都知道,上述代码使用了递归,递归的执行效率比较低!那么既然这么说了,肯定有另外一种的方法咯!
请看:
function copyDeep(parent,child){
var temp;
temp = JSON.stringify(parent);
temp = JSON.parse(temp);
var child = child || {};//如果没有则创建一个
for(var i in temp){
if(temp.hasOwnProperty(i)){//判断parent中的属性是不是自有属性
child[i] = temp[i];
}
}
temp = null;
return child;
}
调用后效果和递归实现的效果一致;
/***********************/
上述参考原文:http://www.jb51.net/article/79707.htm,作出的总结笔记!
/**********************/
关于上述文章中黄色背景处的解释,此处不作为本文重点!!
详情解释见上片文章:http://www.cnblogs.com/adolfvicto/p/7490891.html