阅读 272

JS 中 浅拷贝 与 深拷贝 深度封装

浅拷贝

 
缺点 : 只会拷贝栈内存中的对象内存地址, 两个对象 仍然使用的是一个内存地址,如果修改对象中的属性,那么另一个对象也会被影响(因为内存地址指向同一个堆内存)

 let a = { name: "我是a" }
  /* a的内存地址 指向栈内存中的内容,   */
  // 浅拷贝 拷贝的只是栈内存中 a 的内存地址
  // 如果修改B内存地址中的内容 A也会被修改 因为他俩指向的都是同一个堆内存)

  let b = a
  console.log(b);  // {name:"我是a"}
  b.name = "我是b"  //这里修改了b的name属性(内存地址 指向的 堆内存 内容改变)
  console.log(b);   //{name:"我是b"}
  console.log(a);   //{name:"我是b"}   //因为内存地址中的 堆内存内容被改变了
  

深拷贝

(引用数据类型)

普通数据类型 不存在深拷贝与浅拷贝

方法一: 拷贝对象 ,只拷贝一层, 下面终极方案 可以真正完成 深拷贝(对象 和 数组)
思想 封装一个方法 将要深拷贝的对象传递进去 , 然后for in 遍历 ,方法返回一个新的对象(拷贝以后的对象)

  // 深拷贝  定义一个方法
  function copyObj(obj) {
    let result = {}
    for (let key in obj) {
      result[key] = obj[key]
    }
    return result
  }


  let a = { name: "我是a", age: "awdaw" }
  let b = copyObj(a)    
//深拷贝以后 因为使用的不是使用的一个内存地址
  // 所以b修改堆内存中的值 a 堆内存中的值不会被影响


  b.name = "我是b"
  console.log(b); //{ name:"我是b", age:"awdaw"}
  console.log(a); //{ name: "我是a", age: "awdaw"}


方法二: 拷贝对数组
  // 深拷贝  定义一个方法
  function copyObj(obj) {
    let result = {}
    for (let key in obj) {
      result[key] = obj[key]
    }
    return result
  }
  let a = [1, 2, 3, 4, 5, 6, 7, 8]
  let b = copyObj(a)    //深拷贝以后 因为使用的不是使用的一个内存地址
  // 所以b修改堆内存中的值 a 堆内存中的值不会被影响
  b[0] = "修改了"
  console.log(b); //["修改了", 2, 3, 4, 5, 6, 7, 8]
  console.log(a); //[1, 2, 3, 4, 5, 6, 7, 8]

终极方案: 深拷贝 对象 + 数组 无论值是否为复杂类型 都会被深拷贝

 // 终极方案  根据传入的 类型 进行判断 

  function copyObj(obj) {

    // 判断传入的是什么类型,  根据类型 返回一样类型的返回值
    let result;
    if (Object.prototype.toString.call(obj) == "[object Array]") {
      result = []
    } else if (Object.prototype.toString.call(obj) == "[object Object]") {
      result = {}
    } else {
      return "请输入正确的复杂数据类型"
    }


    for (let key in obj) {
      //使用递归!!!!! 判断值中 是否存在复杂类型  如果存在复杂类型,那么 使用递归 对值在进行一次深拷贝,无论多少层都不会被影响
      if (typeof obj[key] == "object") {
        result[key] = copyObj(obj[key])   //此时这里的值为 {name:122}   深拷贝了,修改不会被影响
        // 跳出本次循环 进入下一次,下面代码不再执行
        break
      }
      result[key] = obj[key]
    }
    // 将深拷贝以后的结果 返回
    return result
  }




  let obj = {
    name: 111, two: {
      name: 122, age: {
        w: 1111
      }
    }
  }


//进行深拷贝 这里是对象
  let newObj = copyObj(obj)
  newObj.two.age.w = "我也被修改楼"
  newObj.two.name = "我修改了"
  console.log(newObj);
  console.log(obj);


//修改以后的结果 不会影响 被拷贝的对象


//进行深拷贝 这里是数组 
 let arr = [1, 2, 3, 4, 5, 6, ["第二层", { name: "第二层中的复杂类型" }]]
  let newArr = copyObj(arr)
  // 修改newArr的内容 arr 不会被影响
  newArr[6][0] = "我也修改了"   //不会影响 arr

  newArr[6][1].name = "修改了"  //不会影响 arr
  console.log(newArr);
  console.log(arr);
//修改以后的结果 不会影响 被拷贝的数组

文章分类
前端
文章标签