其实在工作写代码和面试中,会经常碰到这两个概念:深拷贝,浅拷贝。但今天的重点是深拷贝。
下面我将简单介绍下什么是深拷贝,浅拷贝?
浅拷贝就是直接将一个Object对象所有的属性和属性值复制给另一个Object对象。这样导致的后果是,新对象和老对象相同的Object类型的属性值在内存中的指向是一样的,也就是新对象和老对象的Object类型的同一属性值指向的是同一块内存。因此修改新对象或者原对象,都会互相干扰。
深拷贝是将一个Object对象的内容完全拷贝一份给新对象。修改原对象的属性或者属性值,都不会影响新对象。原对象和新对象是完全独立的,互不影响。
今天的重点是深拷贝,浅拷贝没啥可讲的。 talk is cheap,show me the code!
上浅拷贝代码:
function shallowCopy(obj) {
if (!(obj instanceof object)) {
return obj;
}
let newObj = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
下面重点说说深拷贝
第一个方案是使用JSON.stringify将Object转化为Json字符串,然后在用JSON.parse将json字符串转为Object对象。我们来测试下:
let obj1 = { "name": "Umbrella", "sex": "man" };
let obj2 = obj1;//浅拷贝
obj2.name = "Umbrella1024";
console.log(obj1);
let obj3 = JSON.parse(JSON.stringify(obj1));
console.log(obj3);
obj1.sex = "boy";
console.log(obj3);
下面是运行截图
我们可以看到,浅拷贝后,源对象和新对象会互相影响,改了obj2,obj1就随之改变了。
利用JSON.stringify、JSON.parse实现的深拷贝,是可以实现深拷贝的。 我们再给对象加多点属性,比如加个函数。
let obj4 = {
"name": "Umbrella",
"sex": "man",
"introduce": function () {
console.log("My name is " + this.name);
}
};
obj4.introduce();
let obj5 = JSON.parse(JSON.stringify(obj4));
console.log(obj5);
obj5.introduce();
可以看到采用这种方法,只可以将对象的非Function属性拷贝出来。所以通过JSON.parse和JSON.stringify实现的深拷贝不完美。
那么我分享下我自己写的一个对象深拷贝的方法,这就是我个人比较常用的方案了。
function deepCopy(obj) {
if (obj instanceof Object) {
let newObj = {};
if (Array.isArray(obj)) {
let arr = [];
obj.forEach(item => {
arr.push(deepCopy(item));
})
return arr;
} else {
for (let key in obj) {
let value = obj[key];
if (typeof value == 'function') {
newObj[key] = value.bind(newObj);
} else if (typeof value == 'object') {
if (Array.isArray(value)) {
newObj[key] = [];
value.forEach(item => {
newObj[key].push(deepCopy(item));
})
} else {
newObj[key] = deepCopy(value);
}
} else {
newObj[key] = value;
}
}
}
return newObj;
} else {
return obj;
}
}
可以看到,我写的这个方法中,对属性值为function的做了处理。
我们来对这个deepCopy做测试,看是否是满足需求,可用的。
let obj88 = {
"name": "obj88",
"sex": "man",
"introduce": function () {
console.log("My name is " + this.name);
}
}
let obj8 = {
"name": "Umbrella",
"sex": "man",
"introduce": function () {
console.log("My name is " + this.name);
},
"brothers": [obj88]
};
console.log(obj8);
let obj9 = deepCopy(obj8);
obj9.name = "Flex";
console.log(obj8);
console.log(obj9);
obj88.name = "obj88 Plus";
obj9.introduce();
obj9.brothers[0].introduce();
运行结果:
可以看到,我们的deepCopy函数是能够实现深拷贝的,并且也兼容了属性值类型为function的处理,也是可以拷贝的。
如有错误或者不足的地方,欢迎大佬们来拍砖~
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!