欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ECMAScript-浅拷贝和深拷贝

程序员文章站 2024-03-18 12:00:04
...

一、ECMAScript-浅拷贝和深拷贝
1. 概念

深拷贝:拷贝的对象是新的对象,跟原来的对象不存在共享属性。

浅拷贝:拷贝的对象只是引用原对象的属性。

图解:

我们现在有一个对象在内存中,

ECMAScript-浅拷贝和深拷贝

深拷贝:是两个完全独立的个体

ECMAScript-浅拷贝和深拷贝

浅拷贝:对象和函数部分只是引用

ECMAScript-浅拷贝和深拷贝

2. Object.assign()存在的问题
// Object.assign()常常被用来拷贝对象,但是这种拷贝只是简单的拷贝,不能进行深层次的拷贝,
// 原因:Object.assign()在进行复杂对象的拷贝的时候,只是把引用地址进行的替换,并没有真正的拷贝值
// 简单对象
let target = {
    d: 2,
    e: 3,
    f: 4
}

let source = {
 		g: 4
}
Object.assign(target, source)
console.log(target) // {d: 2, e: 3, f: 4, g: 4} 正常

// 复杂对象
let target = {
  a: {
    b: {
      c: 1
    },
    d: 2,
    e: 3,
    f: 4
  }
}

let source = {
  a: {
    b: {
      c: 1
    },
    d: 2,
    e: 3
  }
}
Object.assign(target, source)
console.log(JSON.stringify(target)) // {"a":{"b":{"c":1},"d":2,"e":3}} 丢失了f

// 拷贝出来的值,值改变两者都不影响,叫深拷贝
let a = 5
let b = a
a = 6
console.log(a, b) // 6 5

// 拷贝出来的值,值改变影响到另一个值,叫浅拷贝
let obj1 = {
  name: 'zhangsan',
  age: 30
}
let obj2 = obj1
console.log(JSON.stringify(obj1)) // {"name":"zhangsan","age":30}
obj1.name = 'lisi' // 改变obj1的值
console.log(JSON.stringify(obj2)) // {"name":"lisi","age":30} obj2的值却改变了
3. 其他拷贝也存在的问题
// 扩展符
const newObj = {...obj}
// Object.creact()
const newObj = Object.creact({},obj)
4. 怎么去实现一个深拷贝
// 方式一:缺陷:如果对象中存在方法则转化就会失败
// 通过JSON.stringify()和JSON.parse()
let obj1 = {
  name: 'zhangsan',
  age: 30,
  study(){
    console.log(this.name)
  }
}
// 先通过JSON.stringify()将其转换成json格式的字符串
let str = JSON.stringify(obj1)
// 再转换成json对象
let obj2 = JSON.parse(str)
// 更改obj1属性的值
obj1.name = 'lisi'
console.log(obj2) // {name: "zhangsan", age: 30} 并未改变,但是方法丢失了

// 方式二:自己实现
let checkType = data => {
  return Object.prototype.toString.call(data).slice(8, -1)
}

console.log(checkType(function(){
  console.log('1111')
}))

let deepClone = target => {
  let targetType = checkType(target)
  let result
  if (targetType === 'Object') {
    result = {}
  } else if (targetType === 'Array') {
    result = []
  } else{
    return target
  }

  for(let key in target) {
    let value = target[key]
    let valueType = checkType(value)
    if(valueType === 'Object' || valueType === 'Array'){
      result[key] = deepClone(value)
    } else if (valueType === 'Function') {
      result[key] = target[key].bind(result)
    } else {
      result[key] = value
    }
  }
  return result
}

// 验证一:
let arr1 = [1, 2, {age: 18}]
let arr2 = deepClone(arr1)
arr2[2].age = 40
console.log(arr1) // 互不影响
console.log(arr2)

// 验证二:
let obj1 = {
  name: 'zhangsan',
  age: 30,
  study(){
    console.log(this.name)
  }
}
let obj2 = deepClone(obj1)

console.log(obj1) 
obj1.name = 'lisi'
console.log(obj1.study === obj2.study) // fasle
相关标签: ECMAScript