JavaScript深复制
转载:http://blog.csdn.net/wanmingtom/article/details/7988284
这原本是StackOverFlow里的一个提问,看到答案后受益良多,于是翻译一下下跟大家分享,原文地址:http://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript
浅复制我就不说了,全部是引用对象,网上列出的深复制的几个例子也都有或多或少的问题,我都试过,某些特殊情况下会出现奇怪的问题,这里摆出一个比较完美的深复制函数(别直接复制了拿去用哦,里面有互动的内容):
上面的这个函数复制一些{}里的玩意儿一点问题都没有,考虑的情况很全面,很周全。但是,现在还没算完,我们来讨论下,如何复制一个“真正”的对象,比如你通过构造函数建立了个对象:
- var User = function(){};
- var newuser = new User();
这种情况的话用上面的函数是完全没问题的,所有的对象的属性全部暴露在外,换句话说都是公有的,public的,随便访问的,没有问题。你可以用for in去迭代里面的属性,不管什么类型,去掉那个“false &&”就可以用,完全没问题。但是,这里存在着一个风险--要知道,对象或实例的属性不可能全部是公有的,一旦存在私有变量(原文中叫状态state),你这样的复制便毫无意义,因为会丢失这些数据。比如下面的代码:
- function Man() {
- var age = 1;
- this.getAge = function () {
- return age;
- }
- this.grow = function () {
- age += 1;
- }
- }
- var man = new Man();
里面的age这个东东,就会出现复制不了的情况了。
除此之外,还有另外一个问题,想象一个没有这些私有变量的情况下,这些代码木有问题,但是,一些对象的构造函数是有参数的,比如我要这样建立一个对象:
function clone(item) {
if (!item) { return item; } // null, undefined values check
var types = [ Number, String, Boolean ],
result;
// normalizing primitives if someone did new String('aaa'), or new Number('444');
//一些通过new方式建立的东东可能会类型发生变化,我们在这里要做一下正常化处理
//比如new String('aaa'), or new Number('444')
types.forEach(function(type) {
if (item instanceof type) {
result = type( item );
}
});
if (typeof result == "undefined") {
if (Object.prototype.toString.call( item ) === "[object Array]") {
result = [];
item.forEach(function(child, index, array) {
result[index] = clone( child );
});
} else if (typeof item == "object") {
// testign that this is DOM
//如果是dom对象,那么用自带的cloneNode处理
if (item.nodeType && typeof item.cloneNode == "function") {
var result = item.cloneNode( true );
} else if (!item.prototype) { // check that this is a literal
// it is an object literal
//如果是个对象迭代的话,我们可以用for in 迭代来赋值
result = {};
for (var i in item) {
result[i] = clone( item[i] );
}
} else {
// depending what you would like here,
// just keep the reference, or create new object
//这里解决的是带构造函数的情况,这里要看你想怎么复制了,深得话,去掉那个false && ,浅的话,维持原有的引用,
//但是我不建议你去new一个构造函数来进行深复制,具体原因下面会解释
if (false && item.constructor) {
// would not advice to do that, reason? Read below
//朕不建议你去new它的构造函数
result = new item.constructor();
} else {
result = item;
}
}
} else {
result = item;
}
}
return result;
}
var copy = clone({
one : {
'one-one' : new String("hello"),
'one-two' : [
"one", "two", true, "four"
]
},
two : document.createElement("div"),
three : [
{
name : "three-one",
number : new Number("100"),
obj : new function() {
this.name = "Object test";
}
}
]
})
- new User({
- bike : someBikeInstance
- });
这种情况下你估计要悲剧,someBikeInstance这货很有可能是在另外的一些上下文中创建的,这个我们获取不来的,至少对于这个函数来说是这样。。
那该咋办呢?其实没什么好的解决办法,要么用for in去迭代,丢掉那些私有变量,要么还是用引用,这些都会出现或多或少的问题,另外一个解决方案是在所有的要被复制的对象里单独建立一个复制函数的属性,就像DOM里的复制节点函数cloneNode一样。
初次翻译,有错误的话,还望谅解!^_^
JavaScript深复制的更多相关文章
- javascript中关于深复制与浅复制的问题
在javascript中,变量的类型分为基本类型和引用类型. 对于基本类型的变量来说,值的复制以及作为函数参数实参传递的过程都是值的复制传递,换句话说,是会在内存中开辟出一个新空间用于存放新的值的.这 ...
- Javascript中的一种深复制实现
在javascript中,所有的object变量之间的赋值都是传地址的,可能有同学会问哪些是object对象.举例子来说明可能会比较好: typeof(true) //"boolean&qu ...
- 深度解析javascript中的浅复制和深复制
原文:深度解析javascript中的浅复制和深复制 在谈javascript的浅复制和深复制之前,我们有必要在来讨论下js的数据类型.我们都知道有Number,Boolean,String,Null ...
- JavaScript 复制对象【Object.assign方法无法实现深复制】
在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...
- JavaScript对象深复制
1.原理 使用JSON,当然需要JSON安全的格式,JSON安全请参考:http://www.cnblogs.com/mengfangui/p/8257269.html 2.示例 <!DOCTY ...
- JavaScript实现深拷贝(深复制) 面试题
1.两种方法实现深拷贝(深复制) (1)方法一:兼容性好,请仔细看代码(网上大部分代码有Bug) (2)方法二:需要对象满足JSON数据格式.JOSN数据格式:http://www.cnblogs.c ...
- javascript 中的深复制 和 其实现方法
首先,我们需要明白什么是深复制(侧重指对象方面)? 在javascript中,复制分为浅复制和深复制,个人理解,浅复制就是直接将引用复制,复制前后的两个对象指向同一个内存地址,对其中一个进行操作,另外 ...
- javascript中的浅复制和深复制
//浅复制:实现基本类型的复制没有问题,但是复制的是引用类型的话,则修改child将会修改parent function extend(parent,child){ var child = child ...
- javascript多种继承方式(函数式,浅复制,深复制,函数绑定和借用)
函数式继承: var object = function (obj) { if (typeof Object.create !== 'undefined') { return Object.creat ...
随机推荐
- Android IOS WebRTC 音视频开发总结(五五)-- 音视频通讯中的抗丢包与带宽自适应原理
本文主要分析webrtc中的抗丢包与带宽自适应原理,文章来自博客园RTC.Blacker,欢迎关注微信公众号blacker,更多详见www.rtc.help 文章内容主要来自中国电信北京研究院丁博士在 ...
- 为什么swing不适合做桌面软件
http://www.zhihu.com/question/19608871 我最近几年做的项目清一色的都是HTML5了,这篇<基于HTML5的电信网管3D机房监控应用>供参考,HTML5 ...
- iOS初学者的AppStore上架应用"菜谱大师"开源了!
本人是一名DoNet程序猿,在业余的时间自学了点iOS,于是就自己弄了一个小菜谱,自己要做菜的时候也就可以用自己的菜谱了. 现在将此应用开源给像我一样对iOS开发有兴趣,并且想学习iOS的园友,毕竟这 ...
- C#局域网桌面共享软件制作(三)
到周末了,继续做这个桌面共享软件,下面是前两篇的链接, 链接 C#局域网桌面共享软件制作(一) 链接 C#局域网桌面共享软件制作(二) 通过对图片进行压缩以后,每张图片大小38K左右(win7/102 ...
- ParameterDirection参数类型
IDataParameter[] paramArray = new IDataParameter[]{ AdoHelper.GetParameter("ReturnValue",D ...
- mariadb的select语句
mariadb的查询流程图 select语句的从句分析顺序:from(过滤表)-->where(过滤行)-->group by(分组)-->having(分组过滤)-->ord ...
- 基于jQuery打造的选项卡向上弹出jquery焦点图切换特效
基于jQuery打造的选项卡向上弹出jquery焦点图切换特效 鼠标经过标题栏,会出现层特效向上滑动,并且在同时进行幻灯片切换,效果十分不错. 有兴趣的童鞋可以下载看看,在IE6方面兼容性也不错,只有 ...
- Android sqlite3工具的使用
sqlite3 <数据库名称> 进入数据库操作模式 eg: sqlite3 contacts.db .tables 查看所有的表 eg: .table .schema 查看查看库中所有表的 ...
- 【译】Spark官方文档——Spark Configuration(Spark配置)
注重版权,尊重他人劳动 转帖注明原文地址:http://www.cnblogs.com/vincent-hv/p/3316502.html Spark主要提供三种位置配置系统: 环境变量:用来启动 ...
- Requests:Python HTTP Module学习笔记(一)(转)
Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...