手写实现深拷贝函数 admin 2023-05-23 15:51:01 篇首语:本文由小编为大家整理,主要介绍了手写实现深拷贝函数相关的知识,希望对你有一定的参考价值。 对象相互赋值的一些关系,分别包括: 引入的赋值:指向同一个对象,相互之间会影响;对象的浅拷贝:只是浅层的拷贝,内部引入对象时,依然会相互影响;对象的深拷贝:两个对象不再有任何关系,不会相互影响; 可以通过JSON.parse来实现深拷贝,但存在以下弊端: 这种深拷贝的方式其实对于函数、Symbol等是无法处理的;并且如果存在对象的循环引用,也会报错的; 一、简单的深拷贝函数实现 自定义深拷贝的基本功能: 二、对其他数据类型的值进行处理 包括:数组、函数、Symbol、Set、Map function isObject(value) const valueType = typeof value return (value !== null) && (valueType === "object" || valueType === "function")function deepClone(originValue) // 判断是否是一个Set类型 if (originValue instanceof Set) return new Set([...originValue]) // 判断是否是一个Map类型 if (originValue instanceof Map) return new Map([...originValue]) // 判断如果是Symbol的value, 那么创建一个新的Symbol if (typeof originValue === "symbol") return Symbol(originValue.description) // 判断如果是函数类型, 那么直接使用同一个函数 if (typeof originValue === "function") return originValue // 判断传入的originValue是否是一个对象类型 if (!isObject(originValue)) return originValue // 判断传入的对象是数组, 还是对象 const newObject = Array.isArray(originValue) ? []: for (const key in originValue) newObject[key] = deepClone(originValue[key]) // 上面的for循环是遍历不到key为Symbol的 // 需要对key为Symbol的清空进行特殊处理 const symbolKeys = Object.getOwnPropertySymbols(originValue) for (const sKey of symbolKeys) // const newSKey = Symbol(sKey.description) newObject[sKey] = deepClone(originValue[sKey]) return newObject// 测试代码let s1 = Symbol("aaa")let s2 = Symbol("bbb")const obj = name: "why", age: 18, friend: name: "james", address: city: "广州" , // 数组类型 hobbies: ["abc", "cba", "nba"], // 函数类型 foo: function(m, n) console.log("foo function") console.log("100代码逻辑") return 123 , // Symbol作为key和value [s1]: "abc", s2: s2, // Set/Map set: new Set(["aaa", "bbb", "ccc"]), map: new Map([["aaa", "abc"], ["bbb", "cba"]])const newObj = deepClone(obj)console.log(newObj === obj) // falseobj.friend.name = "kobe"obj.friend.address.city = "成都"console.log(newObj)console.log(newObj.s2 === obj.s2) // false 三、对循环引用进行处理 function isObject(value) const valueType = typeof value return (value !== null) && (valueType === "object" || valueType === "function")function deepClone(originValue, map = new WeakMap()) // 判断是否是一个Set类型 if (originValue instanceof Set) return new Set([...originValue]) // 判断是否是一个Map类型 if (originValue instanceof Map) return new Map([...originValue]) // 判断如果是Symbol的value, 那么创建一个新的Symbol if (typeof originValue === "symbol") return Symbol(originValue.description) // 判断如果是函数类型, 那么直接使用同一个函数 if (typeof originValue === "function") return originValue // 判断传入的originValue是否是一个对象类型 if (!isObject(originValue)) return originValue // 判断当前传进来的对象是否已经在map中存在,如果是的话, // 直接返回key为这个对象的value,也就是我们所创建出来的newObject对象 if (map.has(originValue)) return map.get(originValue) // 判断传入的对象是数组, 还是对象 const newObject = Array.isArray(originValue) ? []: // 在第一次创建好newObject对象后,将其存去map中,key为需要进行深拷贝的对象,值为新创建好newObject对象 map.set(originValue, newObject) for (const key in originValue) newObject[key] = deepClone(originValue[key], map) // 把map作为函数的第二个参数传入 // 对Symbol的key进行特殊的处理 const symbolKeys = Object.getOwnPropertySymbols(originValue) for (const sKey of symbolKeys) // const newSKey = Symbol(sKey.description) newObject[sKey] = deepClone(originValue[sKey], map) // 把map作为函数的第二个参数传入 return newObject// deepClone(name: "why")// 测试代码let s1 = Symbol("aaa")let s2 = Symbol("bbb")const obj = name: "why", age: 18, friend: name: "james", address: city: "广州" , // 数组类型 hobbies: ["abc", "cba", "nba"], // 函数类型 foo: function(m, n) console.log("foo function") console.log("100代码逻辑") return 123 , // Symbol作为key和value [s1]: "abc", s2: s2, // Set/Map set: new Set(["aaa", "bbb", "ccc"]), map: new Map([["aaa", "abc"], ["bbb", "cba"]])obj.info = objconst newObj = deepClone(obj)console.log(newObj === obj)obj.friend.name = "kobe"obj.friend.address.city = "成都"console.log(newObj)console.log(newObj.s2 === obj.s2)console.log(newObj.info.info.info) 以上是关于手写实现深拷贝函数的主要内容,如果未能解决你的问题,请参考以下文章 天府绿道骑行 最近装Hadoop的心得(内附Hadoop2.9.2详细安装教程) 您可能还会对下面的文章感兴趣: 相关文章 浏览器打不开网址提示“ERR_CONNECTION_TIMED_OUT”错误代码的解决方法 如何安装ocx控件 VMware的虚拟机为啥ip地址老是自动变化 vbyone和EDP区别 linux/debian到底怎么重启和关机 苹果平板键盘被弄到上方去了,如何调回正常? 机器学习常用距离度量 如何查看kindle型号