玖叶教程网

前端编程开发入门

js引用类型深拷贝(js深拷贝循环引用)

一 使用扩展运算符

// 方法一: 扩展运算符深拷贝只能深拷贝拷贝一层,如果value是引用类型的则是浅拷贝
        const obj1 = {
            info: {
                name: 'cgl',
                age: 20
            },
            hobby: 'hhh'
        }
        const newObj = { ...obj1 }
        newObj.info.name = 'wy'
        newObj.hobby = 'ccc'
        console.log('obj', obj1) // { info: {name: 'wy', age: 20}, hobby: 'hhh'}
        console.log('newObj', newObj) // { info: {name: 'wy', age: 20}, hobby: 'ccc'}

二 使用JSON.parse和JSON.stringify

 // 方法二:json-parse和json-stringify实现深拷贝
        const obj7 = {
            name: 'ccc',
            arr: ['1', '2', '3']
        }
        const obj8 = JSON.parse(JSON.stringify(obj7))
        obj7.name = 'ddd'
        obj7.arr.splice(1, 1)
        console.log('obj7--obj8', obj7, obj8)
        // 但是json转换的方法有一个致命的缺陷,如果对象中有value的值是undefined,这样拷贝的时候会直接把value为undefined的键值对给删掉
        const obj9 = {
            name: 'ccc',
            arr: ['1', '2', '3'],
            address: undefined
        }
        const obj10 = JSON.parse(JSON.stringify(obj9))
        obj9.name = 'ddd'
        obj9.arr.splice(1, 1)
        console.log('obj9--obj10', obj9, obj10)

三 使用递归函数进行深拷贝

// 1. 要拷贝的对象
      const obj = {
        name: "撩课",
        age: 18,
        friends: ["小花", "小黑"],
        goodF: {
          name: "小撩",
          age: 19,
          adress: "上海",
          pets: [{ name: "土豆" }, { name: "马铃薯" }],
        },
        bir: new Date(),
      }
      // 判断是不是引用类型的数据
      function isObj(obj) {
        return obj instanceof Object
      }
     // 2.深拷贝函数: 对于键值对的值:如果是值类型,直接给键值对赋新值,如果是引用类型,就递归,直到递归到没有引用类型的value
     // 思想: 遍历某个键值对的时候,值是引用类型的时候,先创建一个相同类型的空对象或者空数组,然后
      function deepCopyObj2NewObj(fromObj, toObj) {
        //  在函数中先检查第一个参数是否有值,
        //  如果没有值那么就初始化一个空的对象
        debugger
        for (var key in fromObj) {
          var fromValue = fromObj[key] // 获取到每一个键值对的value
        // 判断value是不是一个引用类型
        // 如果不是一个一个引用类型,直接就赋值就行了
          if (!isObj(fromValue)) {
            toObj[key] = fromValue
          } else {
            // 如果是引用类型,那么就再调用一次这个方法,去内部拷贝这个对象的所有属性
            var temObj = new fromValue.constructor() // 通过这个方法创建fromValue对应的数据类型,是数组的话就创建一个空数组,是对象的话就创建一个空对象
            deepCopyObj2NewObj(fromValue, temObj)
            // 拷贝friends这个得时候,递归之后获取新的数组temObj,此时friends这个循环走完,接着把friend的循环走完
            toObj[key] = temObj;
          }
          console.log('toobj', toObj)
        }
      }
      var newObj = {}
      deepCopyObj2NewObj(obj, newObj)
      obj.goodF.pets[0]["size"] = "100px"
      console.log(obj);
      console.log(newObj);

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言