js数组的深度克隆,求大神。

寒飞a 2012-02-23 11:48:54
数组属于引用类型,有些时候我们需要克隆一个副本出来使用。简单类型的好办。但数组里包含了复杂类型的就有点不太好办了。看2个列子。

 var arr = new Array(1,2,3); //原始数组。
var newarr = new Array();
newarr = arr.concat();
newarr[0] = newarr[0] + 100;
alert("克隆出来的数组的第一个元素的值为:" + newarr[0] + ",原始数组的值为:" + arr[0]);
//这样对于简单的数据类型可以达到完全克隆的效果。新元素的值为101 ,原始数组里的值不变。1。
//但是,请看下面。


//上面的方法达到了简单数组克隆的目地了。现在新的问题来了
var arr = new Array(); //原始数组。
var a = { name: "张三", age: 20 };
var b = { name: "李四", age: 30 };
var c = { name: "王武", age: 40 };
arr.push(a); arr.push(b); arr.push(c);
var newarr = new Array();
newarr = arr.concat();//复制
//删除其最后一个元素。
newarr.pop();
//更改其中李四的年龄为100
newarr[1].age = 100;
//打印结果看下。
alert("复制的数组的长度为:" + newarr.length + ",李四的年龄为:" + newarr[1].age);
alert("原始的数组的长度为:" + arr.length + ",李四的年龄为:" + arr[1].age);
// 现在新元素的长度变成 2了。而并没有影响到原始数组的数组长度,原始数组的数组长度依然为3.但:数组当中的第二个元素,也就是李四的年龄。。。在我们更改了复制的新数组里面的年龄时,,,原始数组也变了。。这个不是我们想要的结果。。。。
...全文
1000 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
guodefu909 2013-10-09
  • 打赏
  • 举报
回复
找到一个jquery的方法可以实现对象数组的复制:array2 = $.extend(true, {}, array1); 另外找一个说是深度复制的方法,未试验,这里贴出来: <script type="text/javascript"> <!-- 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 --> </script>
jusfr 2012-02-23
  • 打赏
  • 举报
回复
需要实现一个对对象进行深复制的方法,然后对原数据作循环,typeof 元素为object时执行深复制,否则直接传值,最后返回新数组。
寒飞a 2012-02-23
  • 打赏
  • 举报
回复
现在。求第二种数组的完全克隆方式 。
jusfr 2012-02-23
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 luoyehanfei 的回复:]
好了。结贴,发现了。如果引用了jquery文件的话,对Object对象进行任何的属性或者方法的添加。都会造成JQUERY一大部分的功能无法正常使用,原因我就不太明白了,举例吧。

JScript code


Array.prototype.tag = "Object根对象";
function loads() {

var ……
[/Quote]

还可以在使用完自定义扩展后删除掉它,
delete Object.prototype.clone;
delete Array.prototype.clone
寒飞a 2012-02-23
  • 打赏
  • 举报
回复
好了。结贴,发现了。如果引用了jquery文件的话,对Object对象进行任何的属性或者方法的添加。都会造成JQUERY一大部分的功能无法正常使用,原因我就不太明白了,举例吧。

Array.prototype.tag = "Object根对象";
function loads() {

var values = $("#stimes option:selected").text(); //获取SELECT选中的值。
alert(values);
}
//这段代码去掉第一句正常的,如果加上第一句。Jquery将报错。不支持方法了。具体原因
//有兴趣的大神,可以去探访探访,我的解决方法。把代码写在jquery的引用之前。
//这样就没问题了
jusfr 2012-02-23
  • 打赏
  • 举报
回复
如果一定要实现clone方法,非扩展原型及不迭代的方法实现如下

var cloneOpr = {
cloneObj: function (obj) {
var newObj = [];
for (var i in obj) {
newObj[i] = obj[i];
}
return newObj;
},
cloneArr: function (arr) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] === 'object') {
newArr.push(this.cloneObj(arr[i]));
} else {
newArr.push(this[i]);
}
}
return newArr;
}
};
var obj = {
id: 1
};
var obj2 = cloneOpr.cloneObj(obj);
obj2.id = 'Mike';
alert(obj.id);
alert(obj2.id);

var arr = [1, 'a', {id: '20'}];
var arr2 = cloneOpr.cloneArr(arr);
arr[2].id = "new id";
alert(arr[2].id);
alert(arr2[2].id);
jusfr 2012-02-23
  • 打赏
  • 举报
回复
Object.prototype和Array.prototype被添加了新内容,不推荐使用jQuery等框架库时使用这样的自定义扩展。
既然需要修改oldpar的内容,如果只是你说的像usetime字段,那就使用一个新数组存储这个字段;
如果利用oldpar创新全新的内容,那么先声明空数组,遍历时进行操作和添加就好了。
寒飞a 2012-02-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jusfr 的回复:]
将就着用。

JScript code

Object.prototype.clone = function () {
var o = {};
for (var i in this) {
o[i] = this[i];
}
return o;
};
Array.prototype.clone = function () {
……
[/Quote]

你的答案应该是最好的了,虽然我修改了下。我测试了下。是完全克隆出来了,满足了我的需求。。。但是,一个神奇的问题出现了。这样为数组和object添加方法后,jquery库无缘无故报错了。
原始正常的代码:

parzniess = yuanshipraz.concat();//parzniess 为新数组,yuanshipraz为原始数组。
//前面我用这种就会出现那个问题。


新代码:

Object.prototype.clones = function() {
var o = {};
for (var i in this) {
o[i] = this[i];
}
return o;
};
Array.prototype.clones = function() {
var arr = [];
for (var i = 0; i < this.length; i++)
if (typeof this[i] !== 'object') {
arr.push(this[i]);
} else {
arr.push(this[i].clones());
}
return arr;
};
function Inerts() {
parzniess = yuanshipraz.concat();
} //这样,我发觉了jquery库居然运行不走了。。同样的都是返回一个数组对象,我还专门调试了最终
//parzniess 的值,都一样。但是不明白的是为什么jquery库会报错了
寒飞a 2012-02-23
  • 打赏
  • 举报
回复
我把我要克隆的数组发出来给大家看下吧,

var oldpar=new Array();
var a={id:1,name:"1号机台",count:8000,usetime:null}
var b={id:1,name:"2号机台",count:7800,usetime:null}
var c={id:1,name:"3号机台",count:8200,usetime:null}
oldpar.push(a);oldpar.push(b);oldpar.push(c);

现在当用户点击某一个按钮的时候,我要循环这个对象。也就是需要先克隆一个对象。
var newpar=oldpar.clone(); 因为,在用户进行这个操作我会给新克隆的数组赋值,usetime那栏代表着机器呗占用的时间,里面我存放了一个date类型数据。

然后如果用户觉得不满意,重新计算的时候。我要取得原始的数组里的机台信息。
寒飞a 2012-02-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jusfr 的回复:]
将就着用。

JScript code

Object.prototype.clone = function () {
var o = {};
for (var i in this) {
o[i] = this[i];
}
return o;
};
Array.prototype.clone = function () {
……
[/Quote]
这个简洁明了。但是我在想好像有错误吧。我改了下,看是不是该这样?

Object.prototype.clone = function() {
var o = {};
for (var i in this) {
o[i] = this[i];
}
return o;
};
Array.prototype.clone = function() {
var arr = [];
for (var i = 0; i < this.length; i++)
if (typeof this[i] !== 'object') {
arr.push(this[i]);
} else {
arr.push(this[i].clone());
}
return arr;
};
汉尼拔 2012-02-23
  • 打赏
  • 举报
回复
你到底要克隆什么东西?

简单数组 还是 对象 还是 数组里面的元素可能还有对象

第一种 很简单 slice

至于第二和第三种 就要看你克隆的程度了(无限制的克隆毫无意义)
oggmm 2012-02-23
  • 打赏
  • 举报
回复
你必须把a,b,c的值进行复制才行
newarr[1].age = 100;
你更改这个其实是更改了b的值
而新旧数组都是同样引用b
所以会改变

[Quote=引用楼主 luoyehanfei 的回复:]
数组属于引用类型,有些时候我们需要克隆一个副本出来使用。简单类型的好办。但数组里包含了复杂类型的就有点不太好办了。看2个列子。

JScript code
var arr = new Array(1,2,3); //原始数组。
var newarr = new Array();
newarr = arr.concat();
newarr[0] ……
[/Quote]
jusfr 2012-02-23
  • 打赏
  • 举报
回复
将就着用。
Object.prototype.clone = function () {
var o = {};
for (var i in this) {
o[i] = this[i];
}
return o;
};
Array.prototype.clone = function () {
var arr = [];
for (var i = 0; i < this.length; i++)
if (typeof i !== 'object') {
arr.push(i);
} else {
arr.push(i.clone());
}
return arr;
};
var p1 = {
name: 'Rattz',
age: 20,
hello: function () {
return "I'm " + name;
}
};
var p2 = p1.clone();
p2.age++;
alert(p1.age);

var arr1 = [12, 'a', p1,{}];
var arr2 = arr1.clone();
arr2[2].name = 'Mike';
alert(arr1[2].name);
未知数 2012-02-23
  • 打赏
  • 举报
回复
克隆对象的方法:
function objClone(myObj){
if(typeof(myObj) != 'object') return myObj;
if(myObj == null) return myObj;
var myNewObj = new Object();
for(var i in myObj)
myNewObj[i] = objClone(myObj[i]);
return myNewObj;
}
Array.prototype.clone=function(){//为数组添加克隆自身方法,使用递归可用于多级数组
var newArr=new Array();
for(var i=0;i<=this.length-1;i++)
{
var itemi=this[i];
if(itemi.length && itemi.push) itemi= itemi.clone();//数组对象,进行递归
else if(typeof(itemi)=="object") itemi=objClone(itemi);//非数组对象,用上面的objClone方法克隆
newArr.push(itemi);
}
return newArr;
}

基本可以达到完美克隆,length属性也不会丢失(单独用objClone方法也可以克隆数组的所有成员,但是丢失length属性)
使用方式:arr.clone();
寒飞a 2012-02-23
  • 打赏
  • 举报
回复
大神们,不给力啊 。敢不敢上来说几句嘛。。

87,903

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧