js中的深复制和浅复制
在实际情况中经常会遇到对对象复制的问题。比如在处理项目中的一笔多结构的数据存储或者调用,这个时候你就要对对象(json)进行操作,而不同的操作根据不同的需求来定义。其中最常见最普遍的是对对象的复制,重新定义,扩展等。下面我们正对这些问题来进行探讨。要了解对象,我们首先需要了解js的内存分配机制:
var o = {a:1};当我们在给一个变量赋值的时候已经在浏览器中开辟了一块内存出来。这块内存在浏览器中占了一定的空间,这个时候,我们可以称变量 o 为栈,称{a:1}为堆,他们之间的关系可以用下面这个图表示:

我们可以看到,栈上只是存了一个指针,指针就是堆上对象的地址;这个时候我们的程序通过这个指针句柄可以操作堆上的对象;下面我们再声明一个变量b; var b = o;把o复制给b。b通过o获得{a:1}这个对象,但它们并非两个不同的对象,实际上他们的指针都是指向同一个对象。所以当我们通过b重新给{a:1}赋值的时候,我们可以看到o也对应的改变了:
var o = {a:1}, b = o;
b.a = 2;
console.log(o)
//控制台输出提示:Object {a: 2}
这种简单的对对象赋值引用的方式我们可以称之为浅复制,浅复制故名思义它是对整个对象体复制的,没有开辟新内存,所以就会有牵一发动全身的现象出现。如何避免这样的一种情况呢,我们就必须要考虑对对象进行深度复制了。深度复制是对对象枚举,通过查找最末一层值不为对象的属性,然后将该值赋值给新的对象的同名属性上去,由于字符串或者数字的赋值是开辟新内存的,所以我们可以避免上面的说的改变b而导致o的变化。下面是个简单的例子,说明深度复制的原理:
var o = {a:1};
var b = {};
b.a = o.a;
b.a = 2;
console.log(o)
//Object {a: 1}
从以上的代码我们可以看到,b的a属性已经不关联o的任何属性了,它开辟了新内存,可以做自己的事情不会影响到a;我们可以写一个简单的函数来对对象进行深度复制:
var deepCopy= function(source) {
var result={};
for (var key in source) {
result[key] = typeof source[key]===’object’? deepCoyp(source[key]): source[key];
}
return result;
}
当然,说到对象不要忘记我们的array,它也是属于对象类型的。但是对于数组我们有更简便的方法可以用
1.slice()
var a = [1];
var b = a.slice(1);
2.concat()
var a = [1];
var b = [].content(a);
3.组合兼容函数,我们直接上zepto的源码:
function extend(target, source, deep) {
for (key in source)
if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
if (isPlainObject(source[key]) && !isPlainObject(target[key]))
target[key] = {}
if (isArray(source[key]) && !isArray(target[key]))
target[key] = []
extend(target[key], source[key], deep)
}
else if (source[key] !== undefined) target[key] = source[key]
}
原理和上面写的deepCopy一样,遇到对象就枚举,直到它的值是字符串或者数字,然后给新的对象添加属性并且赋值。
ps:遗憾的事诺大的underscore.js竟然不支持深度复制,这让我着实头痛。无奈只有选zepto来辅助了。
js中的深复制和浅复制的更多相关文章
- js中的深复制与浅复制
前言 所谓深复制与浅复制(深拷贝与浅拷贝),乍一听感觉听高大上,像是一个非常难理解的概念,其实我们平常项目开发都是在用的,只是你可能不知道该怎么叫它的名字而已,就像你听熟了一首歌,就是不知道这首歌叫什 ...
- Java中对象的深复制和浅复制详解
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...
- Java中的深复制与浅复制
1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不 复制它所引用的对象. ...
- C#中的深复制与浅复制
C#中分为值类型和引用类型,值类型的变量直接包含其数据,而引用类型的变量则存储对象的引用. 对于值类型,每个变量都有自己的数据副本,对一个变量的操作不可能影响到另一个变量.如 class Progra ...
- Java中的clone()----深复制,浅复制
这篇文章主要介绍了Java中对象的深复制(深克隆)和浅复制(浅克隆) ,需要的朋友可以参考下 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他 ...
- js的深复制与浅复制
什么是深复制和浅复制? 深复制和浅复制的概念只存在于对象array和数组obj上. 浅复制是:模糊复制,就是不管对方是字符串类型还是引用类型都通通复制过来.结果两个变量的内容会同时变化. 深复制是:有 ...
- .Net深复制、浅复制
在.Net,大家都知道引用类型的深复制.浅复制吧. ,一般int等值类型是值类型(复制时是直接传值),一般的类(List<T>,Class)是引用类型(复制时传地址),默认是浅复制.若ob ...
- C++学习基础七——深复制与浅复制
一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和char *str两个成员变量, 当深 ...
- iOS 集合的深复制与浅复制
概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对象内存到另一块内存中. 一图以蔽之 再简单些说:浅复制就是指针拷贝:深复制 ...
随机推荐
- MVC中的常见问题
1. The model backing the 'MusicStoreDBContext' context has changed since the database was created. ...
- 浅析MVC模式与三层架构的区别01
三层架构和MVC是有明显区别的,MVC应该是展现模式(三个加起来以后才是三层架构中的UI层)三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI ...
- CR LF的由来
学习Esperanto时用到一款叫做Kajero的软件,支持世界语特殊字符编辑. 在Option菜单中有个选项,End of line 列出了四种换行方式 这四种都是由基本CR和LF组成.那么CR和L ...
- MongoDB基本管理命令
MongoDB是一个NoSQL数据库系统:一个数据库可以包含多个集合(Collection),每个集合对应于关系数据库中的表:而每个集合中 可以存储一组由列标识的记录,列是可以自由定义的,非常灵活,由 ...
- easyui自定义标签 datagrid edit combobox 手动输入保存不上问题解决办法
使用onEndEdit事件(该事件可以获取到editor对象,onAfterEdit事件获取不到Editor对象) 通过editor拿到输入数据并保存. int ci = 0; for(Column ...
- 数据库.bak文件还原报错的处理办法
今天从网上下了个Demo,里面有个.bak文件,就试着还原了一下,结果发现报了错.是了两种方式导入,都不行. 最终找到了解决办法: 可以直接用sql语句对.bak文件进行还原. RESTORE DAT ...
- jsp_内置对象_request
request内置对象是使用最多的一个对象,其主要作用是接收客户端发送来的请求信息.如请求的参数.发送的头信息等都属于客户端发送来的信息.request是javax.servlet.http.Http ...
- Linux的.a、.so和.o文件
在说明Linux的.a..so和.o文件关系之前,先来看看windows下obj,lib,dll,exe的关系 windows下obj,lib,dll,exe的关系 lib是和dll对应的.lib是静 ...
- 第十一章:使用Apriori算法进行关联分析
- 记录参加“牛津计划.Docker在线黑客松”比赛的过程
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...