如何實現 JavaScript 對象的深拷貝?需要複製後的對象是全新的,所有的成員包括成員函數在內。
function $clone(origin) {
if (typeof origin != "object") {
return origin;
}
var cloned;
if (origin instanceof Array) {
cloned = [];
for ( var i = 0; i < origin.length; i++) {
if (typeof origin[i] == "object") {
cloned[i] = $clone(origin[i]);
}
else {
cloned[i] = origin[i];
}
}
}
else {
cloned = {};
for ( var j in origin) {
if (typeof origin[j] == "object") {
cloned[j] = $clone(origin[j]);
}
else {
cloned[j] = origin[j];
}
}
}
return cloned;
};
這個無法拷貝函數啊
@byvoid 这个我用来做继承用的,比如Child.prototype = $clone(Parent.prototype),函数是可以拷贝过去的.
@sumory 函數不是深拷貝啊,而且成員的 instanceof 不可用了。
@byvoid 你确定没有搞错? 测试下这个:
function Test() {
this.name = 'test';
}
function FatherTest() {
}
FatherTest.prototype.parts = [5,1,2];
FatherTest.prototype.printM = function(){
print('this is printM from Father:'+ this.sex);
};
Test.prototype = $clone(FatherTest.prototype);//深入拷贝
Test.prototype.sex = 'male';
var test = new Test();
print('-------key in test--------');
for(var key in test){
print(key +':'+test[key]);
}
print('-------test继承的方法--------');
test.sex = 'changed sex';
test.printM();
print('-------改变test的数组--------');
test.parts.push(3);
print(test.parts);
var father= new FatherTest();
print(father.parts);//不再会被test.parts.push(3);影响
print('-------instanceof--------');
print(test.parts instanceof Array);
看下结果,可以解答你的问题了
@sumory 這個實現對於函數類型還是淺拷貝,沒有真正複製一個函數。另外試試拷貝過的Date,instanceof不管用。還有,互相引用的兩個對象會遞歸到棧溢出。
@byvoid 我试了下Date类型的确实不能正确instanceof了;不知道你说的“栈溢出”的场景是?
@byvoid 请问为何要拷贝Date,Date是js中的引用类型,如何去复制,就像你无法去复制Object一样。另你所说的instanceof,请参考我的代码。
function ss(){
this.name='ss';
this.test=['a','b','c'];
}
ss.prototype.age='12';
ss.prototype.sayName=function(){
alert(this.name);
}
function subObject(o){
function b(){};
b.prototype=o;
return new b();
}
var cc=subObject(new ss());
var dd=subObject(new ss());
cc.name='I\'m cc';
dd.test.push('d');
for (var key in cc){
console.log(key+':'+cc[key]);
}
for (var key in dd){
console.log(key+':'+dd[key]);
}
var ee=subObject(new Date());
alert(ee instanceof Date); //true 没有继承任何date的方法
@sumory 這個例子,無論複製 obj1 還是 obj2 ,都會棧溢出。
var obj1 = {
ref: null
};
var obj2 = {
ref: obj1
};
obj1.ref = obj2;
@byvoid 循环是普遍问题吧,应该避免这样的编程方式并加检测机制的,就是不太了解js里应该怎么写
碰到函数时用匿名函数包一层: (function (c, a) { fn,apply(c, a); }(context, arg)) context为你的新上下文,其他的,你懂的
忘记return了,还要包一层。。。和bind一样的
return JSON.parse(JSON.stringify(origin));
这种只适用于Function以外的对象