Prechádzať zdrojové kódy

深拷贝工具函数考虑循环引用和多处引用同一个对象的情况。

任一存 3 rokov pred
rodič
commit
12b60972fc
1 zmenil súbory, kde vykonal 10 pridanie a 7 odobranie
  1. 10 7
      packages/code/src/utils/other.js

+ 10 - 7
packages/code/src/utils/other.js

@@ -80,29 +80,32 @@ export function isValidPhoneNumber(value) {
 }
 
 // 深拷贝
-export function deepClone(target) {
+export function deepClone(target, hash = new WeakMap()) {
   // 定义一个变量
-  let result
+  let result = null
   // 如果当前需要深拷贝的是一个对象的话
   if (typeof target === 'object') {
-    // 如果是一个数组的话
-    if (Array.isArray(target)) {
+    if (hash.has(target)) { // 如果是循环引用
+      result = hash.get(target)
+    } else if (Array.isArray(target)) { // 如果是一个数组的话
       result = [] // 将result赋值为一个数组,并且执行遍历
+      hash.set(target, result)
       for (let i in target) {
         // 递归克隆数组中的每一项
-        result.push(deepClone(target[i]))
+        result.push(deepClone(target[i], hash))
       }
       // 判断如果当前的值是null的话;直接赋值为null
     } else if (target === null) {
       result = null
-      // 判断如果当前的值是一个RegExp对象的话,直接赋值    
+      // 判断如果当前的值是一个RegExp对象的话,直接赋值
     } else if (target.constructor === RegExp) {
       result = target
     } else {
       // 否则是普通对象,直接for in循环,递归赋值对象的所有值
       result = {}
+      hash.set(target, result)
       for (let i in target) {
-        result[i] = deepClone(target[i])
+        result[i] = deepClone(target[i], hash)
       }
     }
     // 如果不是对象的话,就是基本数据类型,那么直接赋值