fangchaolong
文章57
标签24
分类10

浅拷贝和深拷贝的区别

实现深拷贝的方式:1、赋值;2、解构赋值;3、JSON.parse(JSON.stringify())

1、赋值

一、对于基本数据类型(Number,String, Boolean….)来说,与其说是深拷贝,严格来说,它们叫做赋值。

  1. let a = 5;
  2. let b = a;
  3. b = 3;
  4. console.log(a, b); // 5 3

二、对于引用数据类型(Object,Array)的深浅拷贝有很多方法,我们依次来看一下:

1. 直接通过赋值,然后进行修改,结果是浅拷贝。

  1. // 数组与对象的赋值,都叫做浅拷贝
  2. let arr = [1, 2, 3];
  3. let newArr = arr;
  4. newArr.push(4);
  5. console.log(arr, newArr);

avatar

2. 使用数组解构进行拷贝:分为两种情况:

情况一:对一维数组使用解构,进行拷贝,结果是深拷贝
  1. let arr = [1, 2, 3];
  2. let newArr = [...arr];
  3. newArr.push(4);
  4. console.log(arr, newArr);

avatar

情况二:对多维数组使用解构,进行拷贝,结果是浅拷贝
  1. let arr = [[1, 2, 3], [4, 5, 6]];
  2. let newArr = [...arr];
  3. newArr[0].push(4);
  4. console.log(arr, newArr);

avatar

3. 使用JSON.Parse(JSON.stringify()),实现深拷贝。

先将一个JavaScript对象转为一个JSON字符串,再转化为JSON对象。
缺点:a、不能拷贝对象上的原型连的属性和方法; b、不能拷贝属性是模板字符挥着正则表达式,c、不能拷贝value值是new Date(),d、不能拷贝value值是:undefined、symbol 和函数这三种情况,会直接忽略。
  1. let list = [
  2. { id: 1, name: '张三' },
  3. { id: 2, name: '李四' },
  4. { id: 3, name: '王五' },
  5. ]
  6. let newList = JSON.parse(JSON.stringify(list));
  7. newList.push({ id: 4, name: '兜兜' });
  8. console.log(list, newList);

avatar

三. 实现深拷贝的Function函数

写法一:
  1. let objc = {
  2. name: '张三', // 基本数据类型
  3. age: 18, // 基本数据类型
  4. objInfo: { // 引用数据类型:Object
  5. sex: '女',
  6. hobby: '游泳'
  7. },
  8. arr: [1, 2, 3] // 引用数据类型: Array
  9. }
  10. function deepClone(info) {
  11. // 数组的constructor会指向Array() { [natice code] }
  12. // 对象的constructor会指向Object() { [native code] }
  13. const targetInfo = info.constructor === Array ? [] : {};
  14. // for in 即可以遍历对象,也可以遍历数组
  15. for (let keys in info) {
  16. if (info.hasOwnProperty(keys)) {
  17. // keys可能有三种类型:基本数据类型, Object, Array
  18. // 如果是引用数据类型
  19. if (info[keys] && typeof info[keys] === 'object') {
  20. // 这行可写可不写
  21. // targetInfo[keys] = info[keys].constructor === Array ? [] : {};
  22. // 递归
  23. targetInfo[keys] = deepClone(info[keys])
  24. } else { // 如果是基本数据类型
  25. targetInfo[keys] = info[keys];
  26. }
  27. }
  28. }
  29. return targetInfo
  30. }
  31. let newObj = deepClone(objc)
  32. newObj.name = '李四'
  33. newObj.arr.push('打豆豆')
  34. console.log(objc, newObj);
写法二:
  1. let obj = {
  2. name: '穗穗',
  3. age: 18,
  4. info: {
  5. sex: '女',
  6. height: 162
  7. },
  8. arr: [1,2,3]
  9. }
  10. const obj1 = deepClone(obj)
  11. function deepClone(info) {
  12. // 判断info的数据类型,如果是基本数据类型或为赋值,直接返回
  13. // 如果info未赋值 ==> let info; info=undefined
  14. // info == null 相当于if (info === null || info === undefined)
  15. // info == null为true,info === null为false,所以此处用==
  16. if (typeof info !== 'object' || info == null) {
  17. return info;
  18. }
  19. let resultObj;
  20. if (info instanceof Array) {
  21. resultObj = []
  22. } else resultObj = {};
  23. for (let key in info) {
  24. if (info.hasOwnProperty(key)) {
  25. resultObj[key] = deepClone(resultObj[key])
  26. }
  27. }
  28. return resultObj
  29. }
写法三:
  1. // 深拷贝函数
  2. function deepClone(obj) {
  3. // 1 判断是否是非应用类型或者null
  4. if (typeof obj !== 'object' || obj == null) return obj
  5. // 2 创建一个容器
  6. let cloneObj = new obj.constructor()
  7. // 3 拿到对象的keys,给容器赋值
  8. Object.keys(obj).forEach(v => cloneObj[v] = deepClone(obj[v]))
  9. // 4 返回容器
  10. return cloneObj
  11. }

无以生计,卖文苟延

微信
支付宝