JavaScript 对象的浅拷贝和深拷贝

125 阅读2分钟

一、浅拷贝

浅拷贝:一般指的是只拷贝对象的第一层,如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址

1-1 拓展运算符

const originArr = ["a", [1, 2]]
const cloneArr = [...originArr]
cloneArr[0] = "b"
cloneArr[1][1] = 1
console.log(originArr) //  ["a", [1, 1]]
console.log(cloneArr) // ["b", [1, 1]]

1-2 Object.assign

  • Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
  • 作用就是用来合并对象、拷贝对象(当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝)
let originObj = { a: 'a', b: [1, 2]}
let cloneObj = Object.assign({}, originObj)
cloneObj.a = 'b'
cloneObj.b[0] = 2
console.log(originObj) // { a: 'a', b: [2, 2]}
console.log(cloneObj)  // { a: 'b', b: [2, 2]}

1-3 slice(0)

const originArr = ["a", [1, 2]]
const cloneArr = originArr.slice(0)
cloneArr[0] = "b"
cloneArr[1][1] = 1
console.log(originArr) //  ["a", [1, 1]]
console.log(cloneArr) // ["b", [1, 1]]

1-4 concat()

const originArr = ["a", [1, 2]]
const cloneArr = originArr.concat()
cloneArr[0] = "b"
cloneArr[1][1] = 1
console.log(originArr) //  ["a", [1, 1]]
console.log(cloneArr) // ["b", [1, 1]]

二、深拷贝

深拷贝:深拷贝会开辟一个新的堆和栈,两个对象属性完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

2-1 JSON.stringify/parse

// JSON.stringify 是将一个 JavaScript 对象转成一个 JSON 字符串
// JSON.parse 是将一个 JSON 字符串转成一个 JavaScript 对象

const mySymbol = Symbol()
const originObj = {
  name:'hhh',
  age:undefined,
  [mySymbol]:'mySymbol',
  sayHello:function(){
    console.log('Hello World')
  }
}
console.log(originObj) // {name: 'hhh', age: undefined, Symbol(): 'mySymbol', sayHello: ƒ}
const cloneObj = JSON.parse(JSON.stringify(originObj))
console.log(cloneObj) // {name: 'hhh'}

!!! undefined、function、symbol 会在转换成 JSON 字符串的过程中被忽略

2-2 递归 深拷贝

function deepClone(source){
  const targetObj = source.constructor === Array ? [] : {}
  for(let keys in source){ // 遍历目标
    if(source.hasOwnProperty(keys)){
      if(source[keys] && typeof source[keys] === 'object'){
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys]);
      }else{ // 如果不是,就直接赋值
        targetObj[keys] = source[keys];
      }
    }
  }
  return targetObj;
}