js深入系列九(深浅拷贝)

123 阅读1分钟

参考文章

参考文章

1. JSON.parse()

对于简单的对象,拷贝时可用JSON.parse(JSON.stringify(obj)),但是undefined、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 null(出现在数组中时)。函数、undefined被单独转换时,会返回undefined

JSON.stringify用法

2. 重写一个拷贝函数

只针对Array和Object进行拷贝,拷贝一个对象到另外一个对象

const obj1 = {a: 'a', b: 20, c: {c1: null, c2: 2, c3: undefined}, d: [null,undefined,3], e: null, f: undefined, g: false, h: {}}
const arr1 = [1, 'a', undefined, null, {}, {a: 1, b: null, c: undefined}]

// 深浅拷贝
// 第一个参数为布尔值,决定是否深浅拷贝,若省略第一个参数默认为false
function copy() {
  // deep:控制是否深浅拷贝
  // target:返回拷贝的结果
  // source: 需要拷贝的对象
  // name: 对象的key组成的数组
  let deep = false, target, source, name;
  if (typeof(arguments[0]) === 'boolean') {
    source = arguments[1] || ''
    if (arguments[0]) deep = true
  } else {
    source = arguments[0]
  }
  
  target = type(source)
  
  name = Object.keys(source)
  if (name.length === 0) return target
  for (let i = 0; i < name.length; i++) {
    if (type(source[name[i]],true)) {
      deep ? target[name[i]] = copy(true,source[name[i]]) : target[name[i]] = source[name[i]]
      // target[i] = source[name[i]]
    } else {
      target[name[i]] = source[name[i]]
    }
    
  }
  return target
}

// 数组对象类型判断
function type () {
  // bool为true时返回布尔值,为空和false返回[]或者{}
  let source = arguments[0], target, bool = arguments[1] || '';
  source = Object.prototype.toString.call(source).slice(8,-1)
  if (bool) {
    source === 'Array'|| source === 'Object' ? target = true : target = false
  } else {
    source === 'Array' ? target = [] : target = {}
  }
  return target 
}

// 示例:深拷贝
a = copy(true,arr1)
console.log(a)

// 输出
[
    0: 1
    1: "a"
    2: undefined
    3: null
    4: {}
    5: {a: 1, b: null, c: undefined}
]