//关键点: 基本数据直接赋值;对象和数组回调赋值
/* (1)为什么不直接用toString方法?这是为了防止对象中的toString方法被重写,
为了正确的调用toString()版本,必须间接的调用Function.call()方法
(2)为什么不使用typeof来直接判断类型?因为对于Array而言,使用typeof(Array)返回的是object,
所以不能得到正确的Array,这里对于后续的数组克隆将产生致命的问题。 */
/* (1)为什么不直接用toString方法?这是为了防止对象中的toString方法被重写,
为了正确的调用toString()版本,必须间接的调用Function.call()方法
(2)为什么不使用typeof来直接判断类型?因为对于Array而言,使用typeof(Array)返回的是object,
所以不能得到正确的Array,这里对于后续的数组克隆将产生致命的问题。 */
// 方法一
function deepClone(obj){
var o ;
switch (typeof obj){
case "undefined":
o=obj;
break;
case "string":
o=obj+"";
break;
case "number":
o=obj-0;
break;
case "boolean":
o=obj;
break;
case "object" ://null object array
if(obj===null){
o=null;
}else{
if(Object.prototype.toString.call(obj).slice(8,-1)=="Array"){
o=[];
for(var i=0;i<obj.length;i++){
o.push(deepClone(obj[i]));
}
}else{
o={};
for(var k in obj){
o[k]=deepClone(obj[k]);
}
}
}
break;
default:
o=obj;
}
return o;
}
function deepClone1(obj){//适合对象不是特别复杂的情况
//对象属性值为undefined的属性被过滤了 ;如果对象属性值是 函数的话,返回为undedined 如 skill:undefined
return JSON.parse(JSON.stringify(obj));
}
function deepClone2(obj){
var o;
if(Object.prototype.toString.call(obj).slice(8,-1)==="Object"){
o={};
}else if(Object.prototype.toString.call(obj).slice(8,-1)==="Array"){
o=[];
}else{//null undefined 基本类型
return obj;
}
for(var k in obj){
//o[k]=deepClone2(obj[k]); 回调1
//o[k]=arguments.callee(obj[k]);//递归调用 回调2
//回调3 这里这三个回调都可以使用
o[k]= typeof obj[k] ==="object"? arguments.callee(obj[k]):obj[k];//可少调最后一层, typeof =function number等不用递归调用
}
return o;
}
function test(){
var testobj={a:1,
skill:function(){
console.log("bob is coding");
},b:[{bb:"cc",a:"lio"},{b1:"b11111",b3:null,
b4:undefined,b2:{b22:"b222",b21:21}}],c:false};
//console.log(JSON.parse(JSON.stringify(testobj)));
console.log("testobj前",testobj);
var t1=deepClone(testobj);
t1.a="测试";
console.log("testobj后",testobj);
console.log("t1",t1);
}
test();
注:上面部分代码有参考其他博客。http://sentsin.com/web/21.html
http://www.2cto.com/kf/201409/332955.html
http://www.cnblogs.com/kingwell/archive/2012/09/09/2677276.html