关于javascript:一个手写深拷贝

<!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>

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理