想直接复制深度克隆代码的请直接复制:

function clone(obj){var buf;if(obj instanceof Array){buf = [];  //创建一个空数组var i = obj.length;while(i--){buf[i] = clone(obj[i]);}return buf;}else if(obj instanceof Object){buf = {};for(var k in obj){buf[k] = clone(obj[k]);}return buf;}else{return obj;}
}//测试
var a = {name:"amy",age:50
}
var b = clone(a);
console.log(b);

下面是相关知识:

记录一个常见的面试题,javascript中对象的深度克隆,转载自:http://www.2cto.com/kf/201409/332955.html

  今天就聊一下一个常见的笔试、面试题,js中对象的深度克隆。翻了下这个题目,在很多地方出现过,已经算一个老的题目了,但是每年的校招中总会考到,其实想想,这个题目考查的知识点还是蛮多的,尤其是对基础知识的考查。好了,闲话不多说,开始正题。

一、js中的对象

  谈到对象的克隆,必定要说一下对象的概念。

  js中的数据类型分为两大类:原始类型和对象类型。

    (1)原始类型包括:数值、字符串、布尔值、null、undefined(后两个是特殊的原始值,这里不做详细的说明,我的上一篇博客有谈到过一些)

    (2)对象类型包括:对象即是属性的集合,当然这里又两个特殊的对象----函数(js中的一等对象)、数组(键值的有序集合)。

  好了既然对象分为这两类,这两种类型在复制克隆的时候是有很大区别的。原始类型存储的是对象的实际数据,而对象类型存储的是对象的引用地址(对象的实际内容单独存放,为了减少数据开销通常存放在内存中)。ps:说到这里,大家要知道,对象的原型也是引用对象,它把原型的方法和属性放在内存当中,通过原型链的方式来指向这个内存地址。

二、克隆的概念

  浅度克隆:原始类型为值传递,对象类型仍为引用传递。

  深度克隆:所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。

三、浅克隆的表现

1,原始类型

  看下面一段代码:

//数值克隆的表现
var a="1";
var b=a;
b="2";
console.log(a);// "1"
console.log(b);// "2"
//字符串克隆的表现
var c="1";
var d=c;
d="2";
console.log(c);// "1"
console.log(d);// "2"
//字符串克隆的表现
var x=true;
var y=x;
y=false;
console.log(x);// true
console.log(y);// false

从上面的代码大家可以看出,原始类型即使我们采用普通的克隆方式仍能得到正确的结果,原因就是原始类型存储的是对象的实际数据。

2.对象类型

  前面说过,函数式一等对象,当然也是对象类型,但是函数的克隆通过浅克隆即可实现

var m=function(){alert(1);};
var n=m;
n=function(){alert(2);};console.log(m());//1
console.log(n());//2
大家能看到,我们直接通过普通赋值的方式,就实现了函数的克隆,并且不会影响之前的对象。原因就是函数的克隆会在内存单独开辟一块空间,互不影响。好了,说了这个特殊的”关系户“以后,我们来说说普通的”选手“。为了方便后续的代码表现,我这里定义一个复杂的对象类型oPerson。下面看一下对象类型的浅复制有什么危害:
var oPerson={oName:"rookiebob",oAge:"18",oAddress:{province:"beijing"},    ofavorite:["swimming",{reading:"history book"}],skill:function(){console.log("bob is coding");}
};
function clone(obj){var result={};for(key in obj){result[key]=obj[key];}return result;
}
var oNew=clone(oPerson);
console.log(oPerson.oAddress.province);//beijing
oNew.oAddress.province="shanghai";
console.log(oPerson.oAddress.province);//shanghai

通过上面的代码,大家能看到,经过对象克隆以后,我修改oNew的地址,发现原对象oPerson也被修改了。这说明对象的克隆不够彻底,那也就是说深度克隆失败!

四、深克隆的实现

  为了保证对象的所有属性都被复制到,我们必须知道如果for循环以后,得到的元素仍是Object或者Array,那么需要再次循环,直到元素是原始类型或者函数为止。为了得到元素的类型,我们定义一个通用函数,用来返回传入对象的类型。

//返回传递给他的任意对象的类
function isClass(o){if(o===null) return "Null";if(o===undefined) return "Undefined";return Object.prototype.toString.call(o).slice(8,-1);
}

PS:Object.prototype.toString.call(o)能直接返回对象的类属性,形如"[object class]"的字符串,我们通过截取class,并能知道传入的对象是什么类型。

当然这里有两个疑问需要解释下:

  

  (1)为什么不直接用toString方法?这是为了防止对象中的toString方法被重写,为了正确的调用toString()版本,必须间接的调用Function.call()方法

  (2)为什么不使用typeof来直接判断类型?因为对于Array而言,使用typeof(Array)返回的是object,所以不能得到正确的Array,这里对于后续的数组克隆将产生致命的问题。

下面就是真正的深度克隆

//深度克隆
function deepClone(obj){var result,oClass=isClass(obj);//确定result的类型if(oClass==="Object"){result={};}else if(oClass==="Array"){result=[];}else{return obj;}for(key in obj){var copy=obj[key];if(isClass(copy)=="Object"){result[key]=arguments.callee(copy);//递归调用}else if(isClass(copy)=="Array"){result[key]=arguments.callee(copy);}else{result[key]=obj[key];}}return result;
}
//返回传递给他的任意对象的类
function isClass(o){if(o===null) return "Null";if(o===undefined) return "Undefined";return Object.prototype.toString.call(o).slice(8,-1);
}
var oPerson={oName:"rookiebob",oAge:"18",oAddress:{province:"beijing"},    ofavorite:["swimming",{reading:"history book"}],skill:function(){console.log("bob is coding");}
};
//深度克隆一个对象
var oNew=deepClone(oPerson);oNew.ofavorite[1].reading="picture";
console.log(oNew.ofavorite[1].reading);//picture
console.log(oPerson.ofavorite[1].reading);//history bookoNew.oAddress.province="shanghai";
console.log(oPerson.oAddress.province);//beijing
console.log(oNew.oAddress.province);//shanghai

 从上面的代码可以看到,深度克隆的对象可以完全脱离原对象,我们对新对象的任何修改都不会反映到原对象中,这样深度克隆就实现了。

  这里要注意一点的就是:为什么deepClone这个函数中的result一定要判断类型?这里有一种情况,如果你的result直接是{}对象,我明明传进去的是一个数组,结果你复制完了以后,变成了一个对象了。

//深度克隆
function deepClone(obj){var result={},oClass=isClass(obj);// if(oClass==="Object"){//     result={};// }else if(oClass==="Array"){//     result=[];// }else{//     return obj;// }for(key in obj){var copy=obj[key];if(isClass(copy)=="Object"){result[key]=arguments.callee(copy);}else if(isClass(copy)=="Array"){result[key]=arguments.callee(copy);}else{result[key]=obj[key];}}return result;
}
function isClass(o){if(o===null) return "Null";if(o===undefined) return "Undefined";return Object.prototype.toString.call(o).slice(8,-1);
}
//克隆一个数组
var arr=["a","b","c"];
var oNew=deepClone(arr);
console.log(oNew);//Object {0: "a", 1: "b", 2: "c"}

转载:https://www.cnblogs.com/jq-melody/p/4499333.html

javascript中对象的深度克隆相关推荐

  1. java中实现对象的深度克隆

    1.什么是深度拷贝和浅拷贝 python中有深度拷贝(也可以叫深度克隆)和浅拷贝,同样在java中很多时候需要深度拷贝对象,所谓的深度拷贝对象指的就是对于对象的所用数据及其全部进行copy一份,变成两 ...

  2. JavaScript中对象(Object)的方法

    JavaScript中对象方法总结: 资料来源:网道-互联网开发文档 [https://wangdoc.com/] 1.Object.getPrototypeOf(Object) Object.get ...

  3. javascript中对象_了解JavaScript中的承诺

    javascript中对象 我向您承诺,到本文结束时,您将更好地了解JavaScript. 我与JavaScript有一种"爱与恨"的关系. 但是尽管如此,JavaScript一直 ...

  4. 删除javaScript中对象的属性

    删除javaScript中对象的属性 语法 delete 对象.属性;

  5. javascript中对象的assign()方法

    javascript中对象的assign()方法 Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 语法: Object.assign( ...

  6. Java对象的深度克隆

    文章目录 前言 代码 后记 前言 日常写代码过程中我们需要对数据和对象等进行克隆,然而对引用类型必须要自己重写clone()方法,对于复杂的对象并不那么好写,而且每个对象都需要重写一次.这里我不重写c ...

  7. JavaScript 中对象的属性类型

    对象的属性类型 JavaScript 中的对象的属性包括数据属性和访问器属性,在 JavaScript 引擎的内部实现中定义了用于描述属性(property)的特性(attribute).规范中将特性 ...

  8. javascript中对象、JSON格式数据、创建对象的方式、数据类型分类及特点

    对象 对象指:具体的一个实物,javascript中对象是指一组没有顺序的属性和方法的集合,所有的事物都是对象,例如:函数,数组,字符串等.属性指事物的特征,一般为名词表示:方法指对象的行为,一般用动 ...

  9. javascript 无法修改 数组中对象_谈谈JavaScript中对象建立(Object)

    在这篇文章中我将会着重说明如何创建JavaScript里的对象(Object). 对象(Object)是什么? 在开始介绍如何创建对象前,我们要知道对象是什么.对象(Object)简单地来说,就是一堆 ...

  10. JavaScript中对象数据存储

    JS中对象数据存储 对象数据存储在堆栈中.栈的数据读取,写入速度快,但是存储的内容较少.堆的读取和写入速度慢,但是存储的内容多.举个例子来说就像电脑中内存和硬盘,内存就像栈,需要经常获取,写入速度比较 ...

最新文章

  1. hibernate异常:not-null property references a null or transient value
  2. 站点分析基础概念之目标转化率
  3. Python 深拷贝和浅拷贝
  4. windows 8   远程桌面(RemoteFX )
  5. intellij idea 主题下载网站
  6. vue+html5实现分类、商品分类、类别、菜单的左右层级布局两种不同精美样式
  7. 最详细教学--实现win10 多用户同时远程登录内网机--win10+frp+rdpwrap+阿里云服务器
  8. 如何禁止软件联网,防止软件自动更新
  9. 我的世界java版骨头指令_我的世界:如何调出“啃骨头”隐藏皮肤?1个没人知道的mc彩蛋...
  10. IT“茫一代”转型记:创业维艰 苦乐皆有
  11. NO.003-2018.02.08《江城子·乙卯正月二十日夜记梦》宋代:苏轼
  12. R语言学习记录:unique()函数
  13. Centos7 安装Nexus
  14. 学习ios牛人40天精通iOS开发的学习方法
  15. 历时5年打造开源芯片生态的一块拼图——SERVE平台
  16. 使用mint ui(一)
  17. SpringBoot2.x整合Dubbo(直连模式)
  18. 如何才能写出优秀作文?猿辅导:生活的观察与感受非常重要
  19. 移动硬盘文件或目录损坏且无法读取解决方法
  20. Oracle - 级联删除

热门文章

  1. libuv 原理_nodejs如何利用libuv实现事件循环和异步
  2. 马尔科夫决策过程(MDP) : BlackJack问题(MC-ES)
  3. 翻译: Keras 标准化:TensorFlow 2.0 中高级 API 指南
  4. pyspark若不能运行,需指定支持版本的java:os.environ[‘JAVA_HOME‘] = ‘F:\Java15.0.2‘
  5. 相同的树 深度优先搜索
  6. Centos Python安装graphviz和pydotplus
  7. 计算机科学导论_学长说专业 | 计算机科学与技术
  8. jar命令成功完成 java -jar 命令却提示“没有主清单属性”!
  9. 403. Frog Jump
  10. 二元函数极值问题:最小二乘法