JS中,一般的赋值传递的都是对象/数组的引用,并没有真正的深拷贝一个对象,如何进行对象的深拷贝呢?

var a = {name : 'miay'};
var b = a;
b.name = 'Jone';
console.log(a.name) //Jone

上述代码中,b指向a所指向的栈对象,也就是说a,b指向同一个栈对象,这种属于对象的浅拷贝。

var a = {name : 'miay'};
var b = Object.assign({},a);
console.log(a === b) //false
b.name = 'chris';
console.log(a.name) //miya

上述代码将原对象拷贝到一个空对象中,a,b指向的是不同的栈对象,所以对b.name重新赋值不会影响到a.name,但是如果a.name是一个对象的引用,而不是一个字符串,那么a.nam和b.name指向的栈空间就是同一个了,看下面的栗子:

var a = {name:{firstName:"tang",lastName:"jiao"}}
var b = Object.assign({},a)
console.log(a === b); //false
b.name.firstName = "chen"
console.log(a.name.firstName) //chen

可以看出,Object.assign只是介于对象的深克隆和浅克隆之间的一种拷贝。具体来说也只是浅拷贝。对于对象属性值为引用类型时,赋值时也是对于栈对象的引用罢了,那如何真正的进行对象的深拷贝呢?

使用JSON.parse()和JSON.stringify()对对象进行深拷贝

var clone = function(obj){
return JSON.parse(JSON.stringify(obj));
}
var a = {
a:function(){console.log('hello world')},
b:{c:1},
c:[1,2,3],
d:'tang',
e:new Date(),
f:null,
g:undefined
}
var b = clone(a);
console.log(b)

可以看出,上述clone的方法会忽略function和undefined的字段,对date类型支持貌似也不友好。而且只能克隆原始对象自身的值,不能克隆它继承的值,参考代码如下:

function Person(name){
this.name = name;
}
var tang = new Person('miya');
var newtang = clone(tang)
tang.constructor === Person //true
newtang.constructor === Person //false
console.log(newtang.constructor) //ƒ Object() { [native code] }

结论:对于纯数据的json对象的深克隆,可以使用JSON.parse()和JSON.stringify()方法,自己可以写个兼容function,undefined,继承,Date的深拷贝的方法:

var clone = function(obj){
if(obj === null) return null;
if(obj.constructor !== 'object') return obj;
if(obj.constructor === Date) return new Date(obj);
if(obj.constructor === RegExp) return new RegExp(obj);
var newObj = new obj.constructor(); //保持继承的原型
for(var key in obj){
if(obj.hasOwnProperty(key)){
var val = obj[key];
newObj[key] = typeof val === 'object' ? arguments.callee(val):val;
}
}
return newObj;
}

经过验证,上述的原型的继承,还是function,undefined,日期,正则等都完美实现深拷贝!

这里运用的就是建立一个新的对象,进行原始对象自有属性的拷贝,遇到引用类型则继续该方法的执行,非引用类型直接赋值。

我唯一知道的就是自己的无知。【完】

【我所知道的只有一件事,那就是我什么也不知道。】 ——苏格拉底

[BGM] The Old Measure  ——Daniel Martin Moore

JS如何进行对象的深克隆(深拷贝)?的更多相关文章

  1. JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘

    一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...

  2. js对象浅拷贝和深拷贝详解

    js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具 ...

  3. js object(对象)

    http://www.cnblogs.com/pingchuanxin/p/5773326.html Object(对象)是在所有的编程语言中都十分重要的一个概念,对于事物我们可以把他们看作是一个对象 ...

  4. JS基础学习——对象

    JS基础学习--对象 什么是对象 对象object是JS的一种基本数据类型,除此之外还包括的基本数据类型有string.number.boolean.null.undefined.与其他数据类型不同的 ...

  5. 程序猿都没对象,JS竟然有对象?

    现在做项目基本是套用框架,不论是网上的前端还是后端框架,也会寻找一些封装好的插件拿来即用,但还是希望拿来时最好自己过后再回过头了解里面的原理,学习里面优秀的东西,不论代码封装性,还是小到命名. 好吧, ...

  6. js中判断对象具体类型

    大家可能知道js中判断对象类型可以用typeof来判断.看下面的情况 <script> alert(typeof 1);//number alert(typeof "2" ...

  7. 浅解析js中的对象

    浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...

  8. js中XMLHttpRequest对象实现GET、POST异步传输

    js中XMLHttpRequest对象实现GET.POST异步传输 /* * 统一XHR接口 */ function createXHR() { // IE7+,Firefox, Opera, Chr ...

  9. 170104、js内置对象与原生对象

    内置对象与原生对象 内置(Build-in)对象与原生(Naitve)对象的区别在于:前者总是在引擎初始化阶段就被创建好的对象,是后者的一个子集:而后者包括了一些在运行过程中动态创建的对象. 原生对象 ...

随机推荐

  1. nmon监控指标

    一.NMON中的各项参数指标: SYS_SUMM:显示当前服务器的总体性能情况 Total System I/OStatistics: Avg tps during an interval:显示采集间 ...

  2. 分辨率与px的关系

    此篇文章的目的用于打印套打的位置计算,顺便科普下知识: 1寸=2.54厘米 14寸=355.6毫米 15.6寸=39.624厘米=396.24毫米: 21寸=533.4毫米 21.7寸=551.18毫 ...

  3. ROC曲线、KS曲线

    一.ROC曲线 ROC曲线由混淆矩阵为基础数据生成. 纵坐标:真阳性比率TPR,预测为正占真正为正的比例. 横坐标:假阳性比率FPR,预测为正占真正为负的比例. 除了roc曲线的纵横坐标外,还有一个准 ...

  4. SpringBoot多数据源中的分布式事务

    虽然现在微服务越来越流行,我们的系统随之也拆分出来好多的模块功能.这样做的目的其实就是为了弥补单体架构中存在的不足.随着微服务的拆分,肯定设计到分库分表,但这之中肯定设计到分布式事务.最典型的例子就是 ...

  5. fiddler https 您的连接不是私密连接 解决方法(不明原理但是照着做成功了,记录下)

    在桌面找到生成的证书 打开chrome chrome://settings/ 导入证书 再次运行fiddler,依次点击Tools下的Options,然后点HTTPS选项卡,再点击actions下的R ...

  6. 吴裕雄--天生自然python编程:turtle模块绘图(2)

    #彩色螺旋线 import turtle import time turtle.pensize(2) turtle.bgcolor("black") colors = [" ...

  7. POJ 3678 2-SAT

    题意:有n个顶点里面可以放数字1或0,给m个限制,每个限制给出两个顶点编号和两编号内数字运算后的结果 思路:很直接的2-SAT,每个点分为1和0两种情况,按限制要求建边,跑tarjan然后判断点是否在 ...

  8. Proto3:Arena分配指南

    Arena分配是仅C++有的功能,在使用Protocol Buffer时,它可以帮助你优化你的内存使用,提高性能.在.proto文件中启用Arena分配会在生成的C++代码中添加处理Arena分配的额 ...

  9. 80 remove duplicates from sorted array 2

    | 分类 leetcode  | Follow up for "Remove Duplicates": What if duplicates are allowed at most ...

  10. HTTP Continuation or non-HTTP traffic

    发现一个 HTTP      Continuation or non-HTTP traffic的数据包,之前没有碰到过.不懂其意义,一看长度,显示1460,与TCP segment of a reas ...