一起了解JS中的深拷贝与浅拷贝
浅拷贝
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:申请域名、虚拟主机、营销软件、网站建设、大竹网站维护、网站推广。浅拷贝是对象的逐位复制。创建一个新对象,该对象具有原始对象中值的精确副本。如果对象的任何字段是对其他对象的引用,则只复制引用地址,即,复制内存地址。
大白话讲就是,浅拷贝是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变。
深拷贝
深拷贝复制所有字段,并复制字段所指向的动态分配内存。深拷贝发生在对象及其引用的对象被复制时。
大白话讲就是,深拷贝则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
Look See See 例子
浅拷贝:它将X
的引用复制到Y
中。因此,X
和Y
的地址是相同的,也就是说它们指向相同的内存位置。
深拷贝:复制X
的所有成员,为Y
分配不同的内存位置,然后将复制的成员分配给Y
,实现深拷贝。这样,如果X
消失了,Y
在内存中仍然有效。
考虑下面的代码:
var employeeDetailsOriginal = { name: '前端小智', age: 18, Profession: '前端开发' };
假设你想创建一个这个对象的副本,这样即使原始值被改变了,仍然可以通过副本得到原始对象的值。
我会这样做:
var employeeDetailsDuplicate = employeeDetailsOriginal; // 浅拷贝
如果咱们改变一个值:
employeeDetailsDuplicate.name = '王大治';
这样操作,咱们的原始对象employeeDetailsOriginal
的属性name
也会跟着改变,因为这里是一个浅拷贝。这样咱们就获取不到原始对象的值了。所以这种拷贝做法是不对的。
但是,通过使用原始employeeDetailsOriginal
变量的属性创建一个全新的变量,就可以创建一个深拷贝副本。
var employeeDetailsDuplicate = { name: employeeDetailsOriginal.name, age: employeeDetailsOriginal.age, Profession: employeeDetailsOriginal.Profession }; // 深拷贝
现在,如果更改employeeDetailsDuplicate.name
,它只会影响employeeDetailsDuplicate
,而不会影响employeeDetailsOriginal
。
谈谈 Object.assign()
Object.assign()
是咱们经常用到的方法,其实这个方法就是浅拷贝。但是它又有一点特殊的地方,就是可以处理第一层的深拷贝。
var employeeDetailsOriginal = { name: '前端小智', family: { name: '前端大家庭' } }; var employeeDetailsDuplicate = Object.assign({}, employeeDetailsOriginal ); employeeDetailsDuplicate.name = '王大治' employeeDetailsDuplicate.family.name = '后端大家庭' console.log(employeeDetailsOriginal ); // { name: "前端小智", family: {name: "后端大家庭"} } console.log(employeeDetailsDuplicate); // { name: "王大冶智", family: {name: "后端大家庭"} }
看上面的例子,属性name
的值并没有跟着变,但是属性中family
的name
的值跟着变了。
如何实现深拷贝
唯一的作法就是克隆这个对象。
对于简单的JSON对象,最简单的方法是 var objectIsNew = JSON.parse(JSON.stringify(objectIsOld)); //如果使用jQuery,可以使用: // 浅拷贝 var objectIsNew = jQuery.extend({}, objectIsOld); // 深拷贝 var objectIsNew = jQuery.extend(true, {}, objectIsOld);
纯JS方法来深拷贝对象(并非方法)
function keepCloning(objectpassed) { if (objectpassed=== null || typeof objectpassed!== 'object') { return objectpassed; } // 临时存储原始的obj的构造 var temporary_storage = objectpassed.constructor(); for (var key in objectpassed) { temporary_storage[key] = keepCloning(objectpassed[key]); } return temporary_storage; } var employeeDetailsOriginal = { name: '前端小智', age: 18, Profession: '前端开发' }; var employeeDetailsDuplicate = (keepCloning(employeeDetailsOriginal)); employeeDetailsOriginal.name = "前端大治"; console.log(employeeDetailsOriginal); console.log(employeeDetailsDuplicate);
总结
了解深拷贝也不仅仅是为了应付面试题,在实际开发中也是非常有用的。例如后台返回了一堆数据,你需要对这堆数据做操作,但多人开发情况下,你是没办法明确这堆数据是否有其它功能也需要使用,直接修改可能会造成隐性问题,深拷贝能帮你更安全安心的去操作数据,根据实际情况来使用深拷贝,大概就是这个意思。
本文转载自:https://segmentfault.com/a/1190000020438346
相关教程推荐:JavaScript视频教程
分享标题:一起了解JS中的深拷贝与浅拷贝
链接分享:http://hbruida.cn/article/cgcjhh.html