发布于2022-10-22 11:16 阅读(1207) 评论(0) 点赞(18) 收藏(4)
都是对原本的对象进行一份复制,差异如下:
浅拷贝
创建一个新对象,如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 。这个内存地址指向同一个堆内存,如果其中一个对象改变了堆内存存放的值,那么所有的对象都会受到影响。
深拷贝
创建一个新对象,如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,则从堆内存中开辟一个新的区域存放该引用类型指向的堆内存中的值,且修改新对象的值不会影响原对象。
放两张我做的蹩脚图加深一下理解:
总而言之,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
const obj1 = {
name: "icy",
age: 20,
hobbies: ["eat", "sleep", "game"],
};
const obj2 = { ...obj1 };
console.log(obj2);
输出:
为了验证是浅拷贝,我们改变一下obj中数组的第一项的值,然后再输出ojb1:
const obj1 = {
name: "icy",
age: 20,
hobbies: ["eat", "sleep", "game"],
};
const obj2 = { ...obj1 };
//修改堆内存中的值
obj2.hobbies[0] = "play";
console.log("修改后obj2", obj2);
console.log("修改后obj1", obj1);
输出结果:
obj1和obj2都受到了影响,验证了浅拷贝。
合并后的新对象
。 const obj1 = {
name: "icy",
age: 20,
hobbies: ["eat", "sleep", "game"],
};
//将拷贝对象与{}空对象合并
const obj2 = Object.assign({}, obj1);
console.log(obj2);
import _ from "lodash"; //导入ladash包
const obj1 = {
name: "icy",
age: 20,
hobbies: ["eat", "sleep", "game"],
};
const obj2 = _.clone(obj1);
console.log(obj2);
console.log(obj1.hobbies === obj2.hobbies); //true
结果如下:
const arr1 = [ 1,2,3,{name:'icy',gender:'美少女']
const arr2 = arr1.concat()
const arr1 = [ 1,2,3,{name:'icy',gender:'美少女']
const arr2 = arr1.slice() //返回剪裁后的数组,这里没有剪裁掉任何项,相当于返回原数组
const obj1 = {
name: "icy",
age: 22,
gender: "美少女",
hobbies: ["eat", "sleep", "game"],
};
const obj2 = JSON.parse(JSON.stringify(obj1)); //深拷贝后的对象
console.log(obj2);
输出:
验证一下深拷贝:
改变obj2的hobbies[0],看下对obj1是否有影响:
obj2.hobbies[0] = "看动漫";
console.log("obj1===", obj1);
console.log("obj2===", obj2);
结论:没有影响,深拷贝成功。
函数
和正则
,因为这两者基于JSON.stringify和JSON.parse处理后,得到的正则就不再是正则(变为空对象),得到的函数就不再是函数(变为null)了。 const obj1 = {
name: "icy",
age: 22,
gender: "美少女",
hobbies: ["eat", "sleep", "game"],
//函数
watchComic: () => {
console.log("icy 我不做人啦");
},
//正则
regx: /^icy{3}$/g,
};
const obj2 = JSON.parse(JSON.stringify(obj1));
console.log("obj2===", obj2);
输出:
函数没了,正则变为空对象。
import _ from "lodash";
const obj1 = {
name: "icy",
age: 20,
hobbies: ["eat", "sleep", "game"],
};
const obj2 = _.clone(obj1); //浅拷贝
console.log(obj2);
console.log(obj1.hobbies === obj2.hobbies); //true
const obj3 = _.cloneDeep(obj1); //深拷贝
console.log("obj3==", obj3); //false
console.log(obj1.hobbies === obj3.hobbies);
输出结果对比:
3. jQuery.extend()方法
jQuery提供了extend方法可以实现深拷贝。
//第一个参数为true,就是深拷贝,为false则是浅拷贝
$.extend(deepCopy, target, object1, [objectN])
import $ from "jquery"
const obj1 = {
name: "icy",
age: 20,
hobbies: ["eat", "sleep", "game"],
};
var obj2 = $.extend(true, {}, obj1);
递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。
下面是大佬写的,考虑到了,Date,正则,函数,对象循环引用(自己引用自己)的一个深拷贝递归:
function deepClone(obj, hash = new WeakMap()) { if (obj === null) return obj; // 如果是null或者undefined就不进行拷贝操作 if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); // 可能是对象(包括函数)或者普通的值 如果是函数或者普通的值不需要深拷贝 if (typeof obj !== "object") return obj; // 是对象的话就要进行深拷贝 if (hash.get(obj)) return hash.get(obj); let cloneObj = new obj.constructor(); // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身 hash.set(obj, cloneObj); for (let key in obj) { if (obj.hasOwnProperty(key)) { // 实现一个递归拷贝 cloneObj[key] = deepClone(obj[key], hash); } } return cloneObj; } let obj = { name: 1, address: { x: 100 } }; obj.o = obj; // 对象存在循环引用的情况 let d = deepClone(obj); obj.address.x = 200; console.log(d);
参考文章:https://segmentfault.com/a/1190000020255831
https://juejin.cn/post/6844904197595332622
原文链接:https://blog.csdn.net/qq_43682422/article/details/127393325
作者:听说你很拽
链接:http://www.qianduanheidong.com/blog/article/444733/a5a28ea68cb4de37de86/
来源:前端黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 前端黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-3
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!