参考文章:
参考文章2的深拷贝代码如下:
function getType(o) { var _t; return ((_t = typeof(o)) == "object" ? o==null && "null" || Object.prototype.toString.call(o).slice(8,-1):_t).toLowerCase(); } function extend(destination,source) { for(var p in source) { if(getType(source[p])=="array"||getType(source[p])=="object") { destination[p]=getType(source[p])=="array"?[]:{}; arguments.callee(destination[p],source[p]); } else { destination[p]=source[p]; } } } var test={a:"ss",b:"dd",c:{d:"css",e:"cdd"}}; var test1={}; extend(test1,test); test1.c.d="change"; //改变test1的c属性对象的d属性 alert(test.c.d); //不影响test
假如:
var test={a:"ss",b:"dd",c:{d:"css",e:"cdd"}}; var test1=[];//使用该方法深拷贝,必须先定义拷贝到的对象,并且初始化 extend(test1,test); test1.c.d="change"; //改变test1的c属性对象的d属性 alert(test.c.d); //不影响test
这样做,的确也把test的数据复制过来了,而且,修改test1.c.d也不会对test造成影响,但是接下来的问题来了,test1的类型改变了,这个时候,我们按照原类型去处理,比如使用array的push方法,就会出错了,chrome监视情况如下
代码:
Chrome对象监视
无废话,正确代码如下
Ext.namespace("GTP.BI");
GTP.BI.Util = {};
GTP.BI.Util.getType = function (o) {
var _t; return ((_t = typeof (o)) == "object" ? o == null && "null" || Object.prototype.toString.call(o).slice(8, -1) : _t).toLowerCase(); }; GTP.BI.Util.copy = function (source) { var destination = GTP.BI.Util.getType(source) == "array" ? [] : {}; //呵呵,联想到了Ext.extend方法 for (var p in source) { if (GTP.BI.Util.getType(source[p]) == "array" || GTP.BI.Util.getType(source[p]) == "object") { destination[p] = GTP.BI.Util.getType(source[p]) == "array" ? [] : {}; destination[p] = arguments.callee(source[p]); } else { destination[p] = source[p]; } } return destination; }
var test = { a: "ss", b: "dd", c: { d: "css", e: "cdd"} };
var test1 = [];
test1 = GTP.BI.Util.copy(test);
test1.c.d = "change"; //改变test1的c属性对象的d属性
alert(test.c.d); //不影响test
重要说明:test1 此时也为Object,它和初始化类型毫无关系。其实这里根本就不需要初始化,当然,若是初始化了,在这里不仅深拷贝了值,而且也拷贝了类型,将test1的初始化值和类型完全覆盖(这样的才是深拷贝么,哇哈哈)。
相对于参考文章二,其实做出的修改很小,主要是添加了命名空间(使用Extjs),另外,改了一下函数,在实现拷贝的时候,不需要传入要拷贝到的地方(destination),而采取动态生成destination对象,解决使用参考文章2中以下问题:
1、拷贝时需要初始化destination类型
2、若初始化错destination类型,会导致拷贝后类型变化的问题。