js 对象的浅拷贝与深拷贝

1、对象的浅拷贝及方法

  • a、定义

拷贝的是源对象的指针,修改其中一个对象,原对象和拷贝对象都会受到影响

  • b、Object.assign(object) 方法
/**
 * 构造函数,用于生成对象实例
 */
function ORIGINOBJ () {
  const obj = {
    A: 'AAAAAAA',
    B: 'BBBBBBB',
    C: function () {
      console.log('yeah!!!')
    },
    D: ['DD1', 'DD2', 'DD3'],
    E: {
      EA: ['EA1', 'EA2', 'EA3'],
      EB: {
        EBA: () => {
          console.log('Wa hahaha!!!!')
        },
        EBB: null,
        EBC: undefined
      }
    },
    F: null,
    G: undefined,
    H: false
  }
  // 遍历生成构造函数 this 对象上的方法、属性,用于生成实例对象
  for (let i in obj) {
    this[i] = obj[i]
  }
}

// 在原对象实例上添加方法、属性
ORIGINOBJ.prototype.speak = function () {
  console.log('wa Haaaaa!!!')
}
ORIGINOBJ.prototype.name = 'ORIGINOBJ'
ORIGINOBJ.prototype.type = undefined

// new 一个对象
const originObject = new ORIGINOBJ()

/**
 * Object.assign 复制对象时,值得注意的是
 * 第一层的数据是深拷贝
 * 第二层以后面层次的则是浅拷贝
 */
const assignObject = Object.assign({}, originObject)
assignObject.A = 'hahah' // 原对象的数据没改变
assignObject.E.EB = 'hahah' // 原对象的数据改变了
console.log(originObject)
console.log(assignObject)

打印结果如下


image.png

二、对象的深拷贝及方法

将原对象拷贝到另一个内存中,修改其中一个对象,另一个对象并不会收到影响,具体方法如下

  • a、利用 JSON.parse(JSON.stringify(originObject)) 的方法深拷贝
/**
 * 构造函数,用于生成对象实例
 */
function ORIGINOBJ () {
  const obj = {
    A: 'AAAAAAA',
    B: 'BBBBBBB',
    C: function () {
      console.log('yeah!!!')
    },
    D: ['DD1', 'DD2', 'DD3'],
    E: {
      EA: ['EA1', 'EA2', 'EA3'],
      EB: {
        EBA: () => {
          console.log('Wa hahaha!!!!')
        },
        EBB: null,
        EBC: undefined
      }
    },
    F: null,
    G: undefined,
    H: false
  }
  // 遍历生成构造函数 this 对象上的方法、属性,用于生成实例对象
  for (let i in obj) {
    this[i] = obj[i]
  }
}

// 在原对象实例上添加方法、属性
ORIGINOBJ.prototype.speak = function () {
  console.log('wa Haaaaa!!!')
}
ORIGINOBJ.prototype.name = 'ORIGINOBJ'
ORIGINOBJ.prototype.type = undefined

// new 一个对象
const originObject = new ORIGINOBJ()

/**
 * JSON.parse(JSON.stringify()) 深拷贝
 * 一、弊端
 * 1、对于值为 undefined 的属性不能复制过来
      (虽然不影响,因为不存在时即为 undefined)
 * 2、对于值为函数的属性不能复制过来
 * 3、不能复制原对象原型上的方法和属性
*/
const jsonObject = JSON.parse(JSON.stringify(originObject))
// 修改深拷贝的对象,原对象的值并不会改变
jsonObject.A = 'hahah'
console.log(originObject)
console.log(jsonObject)
console.log(jsonObject.name) // undefined
console.log(jsonObject.type) // undefined
jsonObject.speak() // 报错 jsonObject.speak is not a function

打印结果如下


image.png
  • b、利用 lodash 插件 的 cloneDeep 方法深拷贝
import _ from 'lodash'
const { cloneDeep } = _

/**
 * 构造函数,用于生成对象实例
 */
function ORIGINOBJ () {
  const obj = {
    A: 'AAAAAAA',
    B: 'BBBBBBB',
    C: function () {
      console.log('yeah!!!')
    },
    D: ['DD1', 'DD2', 'DD3'],
    E: {
      EA: ['EA1', 'EA2', 'EA3'],
      EB: {
        EBA: () => {
          console.log('Wa hahaha!!!!')
        },
        EBB: null,
        EBC: undefined
      }
    },
    F: null,
    G: undefined,
    H: false
  }
  // 遍历生成构造函数 this 对象上的方法、属性,用于生成实例对象
  for (let i in obj) {
    this[i] = obj[i]
  }
}

// 在原对象实例上添加方法、属性
ORIGINOBJ.prototype.speak = function () {
  console.log('wa Haaaaa!!!')
}
ORIGINOBJ.prototype.name = 'ORIGINOBJ'
ORIGINOBJ.prototype.type = undefined

// new 一个对象
const originObject = new ORIGINOBJ()

/**
 * lodash cloneDeep 方法深拷贝
 * 一、优点
 * 1、不存在JSON.parse(JSON.stringify()) 方法的弊端
 * 2、能够完美的深拷贝原来的对象,包括原对象上的原型方法和属性
 * 
 * 二、弊端
 * 1、需要引入 lodash 这个额外的依赖
*/
const cloneDeepObject = cloneDeep(originObject)
// 修改深拷贝的对象,原对象的值并不会改变
cloneDeepObject.A = 'hahah'
console.log(originObject)
console.log(cloneDeepObject)
console.log(cloneDeepObject.name) // ORIGINOBJ
console.log(cloneDeepObject.type) // undefined
cloneDeepObject.speak() // wa Haaaaa!!!

打印结果如下:


image.png
  • c、利用自定义的 cloneDeep 方法深拷贝
/**
 * 构造函数,用于生成对象实例
 */
function ORIGINOBJ () {
  const obj = {
    A: 'AAAAAAA',
    B: 'BBBBBBB',
    C: function () {
      console.log('yeah!!!')
    },
    D: ['DD1', 'DD2', 'DD3'],
    E: {
      EA: ['EA1', 'EA2', 'EA3'],
      EB: {
        EBA: () => {
          console.log('Wa hahaha!!!!')
        },
        EBB: null,
        EBC: undefined
      }
    },
    F: null,
    G: undefined,
    H: false
  }
  // 遍历生成构造函数 this 对象上的方法、属性,用于生成实例对象
  for (let i in obj) {
    this[i] = obj[i]
  }
}

// 在原对象实例上添加方法、属性
ORIGINOBJ.prototype.speak = function () {
  console.log('wa Haaaaa!!!')
}
ORIGINOBJ.prototype.name = 'ORIGINOBJ'
ORIGINOBJ.prototype.type = undefined

// new 一个对象
const originObject = new ORIGINOBJ()

/**
 * 自定义封装的 deepCopy 方法来深拷贝对象
 * 一、优点
 * 1、不存在JSON.parse(JSON.stringify()) 方法的弊端
 * 2、原型上面的属性、方法将被添加到拷贝对象的实例上
 * 3、能够完美的深拷贝原来的对象
 */

function deepCopy (source) {
  let target = Array.isArray(source) ? [] : {}
  for (let i in source) {
    if (typeof source[i] === 'object') {
      target[i] = deepCopy(source[i])
    } else {
      target[i] = source[i]
    }
  }
  return target
}

const deepCopeObject = deepCopy(originObject)
// 修改深拷贝的对象,原对象的值并不会改变
deepCopeObject.A = 'hahah'
console.log(originObject)
console.log(deepCopeObject)

打印结果如下:


image.png

你可能感兴趣的:(js 对象的浅拷贝与深拷贝)