浅拷贝(shellow copy)
先看下边一个例子:
Object.prototype.clone = function () { var newObj = {}, self = this; for (var i in self) { newObj[i] = self[i]; } return newObj; } var obj = { name:"老李头", hobby:["敲代码","压马路"] } var _obj = obj.clone(); obj.hobby.push("打篮球"); console.log(obj.hobby);//["敲代码", "压马路", "打篮球"] console.log(_obj.hobby);//["敲代码", "压马路", "打篮球"]
就像我们看到的,浅拷贝只能复制基本类型的属性,而对于共享对象类型的属性则没有办法。
深拷贝 (deep copy)
在使用深拷贝复制对象时,由于数据类型的不确定性,可能为对象,数组,函数,也可能是以上几种的嵌套。这个时候我们就需要借助递归。
Object.prototype.clone = function () { var self = this, newObj = {}; for(var i in self ){ if( typeof (self[i]) == "object" || typeof (self[i]) == "function"){ newObj[i] = self[i].clone(); }else{ newObj[i] = self[i]; } } return newObj; } Array.prototype.clone = function () { var self = this, newArr = []; for(var i=0,len=self.length;i<len;i++){ if( typeof (self[i]) == "object" || typeof (self[i]) == "function"){ newArr [i] = self[i].clone(); }else{ newArr [i] = self[i]; } } return newArr; } Function.prototype.clone = function () { var self = this, newFn = function () { return self.apply(this,arguments); }; for(var i in self){ newFn[i] = self[i]; } return newFn; } var obj = { name: 'byvoid', likes: ['node'], display: function() { console.log(this.name); }, }; var newObj = obj.clone(); newObj.likes.push('python'); console.log(obj.likes); // 输出 [ 'node' ] console.log(newObj.likes); // 输出 [ 'node', 'python' ] console.log(newObj.display == obj.display); // 输出 false
上面这个实现看起来很完美,它不仅递归地复制了对象复杂的结构,还实现了函数的深拷贝。这个方法在大多数情况下都很好用,但有一种情况它却无能为力,例如下面的代码:
var obj1 = { ref:null }; var obj2 = { ref:obj1 }; obj1.ref = obj2;
这段代码的逻辑非常简单,就是两个相互引用的对象。当我们试图使用深拷贝来复制obj1 和 obj2 中的任何一个时,问题就出现了。因为深拷贝的做法是遇到对象就进行递归复制,那么结果只能无限循环下去。对于这种情况,简单的递归已经无法解决。