手写深拷贝函数

113 阅读2分钟

手写深拷贝函数

将自己的理解和知识点写在代码注释中.(习惯了)

实现深拷贝v1-基本实现

function isObject(value) {
  const valueType = typeof value
  return (value !== null) && (valueType === 'object' || valueType === 'function')
}
function deepCopy(originValue) {
  // 判断是否是对象
  if(!isObject(originValue)) {
    return originValue
  }

  var newValue = {}
  for(const key in originValue) {
    newValue[key] = deepCopy(originValue[key])
  }
  return newValue
}

const obj = {
  name: 'Fhup',
  age: 18,
  friend: {
    name: 'xixi',
    home: {
      count: 5
    }
  }
}

const newObj = deepCopy(obj)
console.log(newObj);

obj.friend.home = 666
console.log(newObj);

实现深拷贝v2-其他类型

function isObject(value) {
  const valueType = typeof value
  return (value !== null) && (valueType === 'object' || valueType === 'function')
}
function deepCopy(originValue) {

  // 判断是否是一个Set类型
  if(originValue instanceof Set) {
    return new Set([...originValue])
  }
  // 判断是否是一个Map类型
  if(originValue instanceof Map) {
    return new Map([...originValue])
  }

  // 创建一个新的Symbol
  if(typeof originValue === 'symbol') {
    return Symbol(originValue.description)
  }

  // 对函数进行处理(直接返回使用同一个,因为函数不需要修改)
  if(typeof originValue === 'function') {
    return originValue
  }

  // 判断是否是对象
  if(!isObject(originValue)) {
    return originValue
  }
  // 优化: 判断传入的是数组还是对象
  var newValue = Array.isArray(originValue) ? [] : {}
  for(const key in originValue) {
    newValue[key] = deepCopy(originValue[key])
  }

  // 对Symbol的key进行特殊的处理
  const symbolKeys = Object.getOwnPropertySymbols(originValue)
  for(const skey of symbolKeys) {
    newValue[skey] = deepCopy(originValue[skey])
  }
  return newValue
}

let s1 = Symbol('aaa')
let s2 = Symbol('bbb')

const obj = {
  name: 'Fhup',
  age: 18,
  friend: {
    name: 'xixi',
    home: {
      count: 5
    }
  },
  hobbies: ['aaa', 'bbb', 'ccc', 'ddd'],
  foo(){
    console.log('foo function');
  },
  [s1]: 'xxx',
  s2: s2,
  set: new Set(['111', '222', '333']),
  map: new Map([['one','oonnee'], ['two', 'ttwwoo'], ['three', 'tthhrreeee']])
}

const newObj = deepCopy(obj)
console.log(newObj);

obj.friend.home = 666
console.log(newObj);

console.log(obj.s2 === newObj.s2) // false

实现深拷贝v3-循环引用

function isObject(value) {
  const valueType = typeof value
  return (value !== null) && (valueType === 'object' || valueType === 'function')
}
function deepCopy(originValue, map = new WeakMap()) {

  if(originValue instanceof Set) {
    return new Set([...originValue])
  }
  if(originValue instanceof Map) {
    return new Map([...originValue])
  }
  if(typeof originValue === 'symbol') {
    return Symbol(originValue.description)
  }
  if(typeof originValue === 'function') {
    return originValue
  }
  if(!isObject(originValue)) {
    return originValue
  }
  // 对循环引用进行处理
  if(map.has(originValue)) {
    return map.get(originValue)
  }
  var newValue = Array.isArray(originValue) ? [] : {}

  map.set(originValue, newValue)

  for(const key in originValue) {
    newValue[key] = deepCopy(originValue[key], map)
  }
  const symbolKeys = Object.getOwnPropertySymbols(originValue)
  for(const skey of symbolKeys) {
    newValue[skey] = deepCopy(originValue[skey], map)
  }
  return newValue
}

let s1 = Symbol('aaa')
let s2 = Symbol('bbb')

const obj = {
  name: 'Fhup',
  age: 18,
  friend: {
    name: 'xixi',
    home: {
      count: 5
    }
  },
  hobbies: ['aaa', 'bbb', 'ccc', 'ddd'],
  foo(){
    console.log('foo function');
  },
  [s1]: 'xxx',
  s2: s2,
  set: new Set(['111', '222', '333']),
  map: new Map([['one','oonnee'], ['two', 'ttwwoo'], ['three', 'tthhrreeee']])
}

obj.info = obj

const newObj = deepCopy(obj)
console.log(newObj);

obj.friend.home = 666
console.log(newObj);

console.log(obj.s2 === newObj.s2) // false


console.log(newObj.info.info.info);