<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>

    let obj = {
      name: 'zjh',
      gender: 'man',
      friend: {
        girl: 'lsq'
      }
    }
    
    function deepClone(data, map = new Map()){
      //判断数据是不是引用类型,如果是引用类型可以直接将值return
      if(typeof data !== 'object'){
        return data
      }
      //存下参数 data 是否时数组的判断,用于再下面遍历的时候使用合适的遍历方式
      let isArray = Array.isArray(data)   

      //引用类型的数据则开始深拷贝
      //判断传递过来的数据是数组还是对象,数组就将 clone 写为数组类型,负责写为普通对象类型
      let clone = Array.isArray(data) ? [] : {}  

      //甄别这个属性有没有已经被克隆下来,避免死循环,如果已经被克隆下来就返回该属性之前存下的值
      if(map.get(data)){
        return map.get(data)
      }
      //如果没有被克隆过,则将 clone 对象保存下来,用于递归时甄别使用
      map.set(data, clone)
      
      //如果参数 data 不是数组就将属性名给保存下来
      let keys = isArray? null: Object.keys(data)

      for (let key in data) {
        //这里有可能存在多层引用数据类型数据嵌套,所以使用递归调用
        clone[key] = deepClone(data[key])   
      }
      return clone
    }

    let newObj = deepClone(obj)
    newObj.name = 'zzz'
    newObj.friend.girl = 'lll'

    console.log('clone', newObj);
    console.log('initial', obj);
  </script>
</body>
</html>

张嘀嗒
9 声望2 粉丝

一个前端小白,更新学习笔记~~