深拷贝

方案一:JSON序列化和解析

比较简单的深拷贝方案,但仅支持基本数据类型和部分引用数据类型

其不支持的类型或情况

  • Symbol
  • Function
  • 循环引用(遇到此情况会报错)
  1. const s1=Symbol()
  2. const obj={
  3. name:'rv',
  4. age:20,
  5. /* Function */
  6. running:()=>{console.log('running')},
  7. /* Symbol */
  8. [s1]:'symbol',
  9. symbol:s1
  10. /* Array */
  11. arr:[1,2,3,4]
  12. /* Object */
  13. friend:{ name:'why',age:18}
  14. }
  15. const copyObj=JSON.parse(JSON.stringify(obj));
  16. console.log(copyObj)
  17. /*
  18. Object{
  19. name: "rv"
  20. age: 20
  21. arr: (4) [1, 2, 3, 4]
  22. friend: {name: 'why', age: 18}
  23. }
  24. */

方案二:手动实现深拷贝

  1. function deepClone(originValuemap=new WeakMap()){
  2. /* Set、Map、WeakSet、WeakMap的拷贝处理 */
  3. if(originValue instanceof Set){
  4. return new Set([...originValue])
  5. }
  6. if(originValue instanceof Map){
  7. return new Map([...originValue])
  8. }
  9. if(originValue instanceof WeakSet||originValue instanceof WeakMap){
  10. return originValue
  11. }
  12. /* Symbol的拷贝处理 */
  13. if(typeof originValue==='symbol'){
  14. if(Symbol.keyFor(originValue)==null){
  15. return Symbol()
  16. }else{
  17. return originValue
  18. }
  19. }
  20. /* 基础数据类型和Function的拷贝处理 */
  21. if(!isObject(originValue)||typeof originValue==='function'){
  22. return originValue
  23. }
  24. /* 检测数组是否存在循环引用 */
  25. if(map.has(originValue)){
  26. return map.get(originValue)
  27. }
  28. /* 数组和普通对象的拷贝处理 */
  29. const newObject=Array.isArray(originValue)?[]:{}
  30. /* String key的拷贝处理 */
  31. for(const key in originValue){
  32. newObject[key]=deepClone(originValue[key],map)
  33. }
  34. /* Symbol key的拷贝处理 */
  35. const symbols=Object.getOwnPropertySymbols(originValue)
  36. for(const key of symbols){
  37. newObject[key]=deepClone(originValue[key],map)
  38. }
  39. map.set(originValue,newObject)
  40. return newObject
  41. }
  42. function isObject(value){
  43. const valueType=typeof value
  44. return (value!==null)&&(valueType==='object'||valueType==='function')
  45. }