JavaScript深浅拷贝

2021-02-17  本文已影响0人  麦西的西

一般来说,我们拷贝数据的时候:
如果是基本数据类型,则会生成新的数据,修改拷贝后的数据不会影响原有数据。
如果是对象/数组,并不会生成新的数据,而是拷贝引用,修改拷贝数据会影响原有数据。

常用的几种拷贝方法

  1. 直接赋值
let person = {
    name: 'Jack'
}
let newPerson = person
newPerson.name = 'Tom'
console.log(person.name) // Tom    修改拷贝后的数据会影响原有数据,浅拷贝
  1. Object.assign()
let person = {
    name: 'Jack',
    otherInfo: {
        age: 22
    }
}
let newPerson = {}
Object.assign(newPerson, person)
newPerson.otherInfo.age = 33
console.log(person.otherInfo.age) // 33    修改拷贝后的数据会影响原有数据,浅拷贝
  1. Array.prototype.concat()
let arr = [1, 2, { name: 'Jack'}]
let newArr = arr.concat([])
newArr[2].name = 'Tom'
console.log(arr[2].name) // Tom    修改拷贝后的数据会影响原有数据,浅拷贝
  1. Array.prototype.slice()
let arr = [1, 2, { name: 'Jack'}]
let newArr = arr.slice(0)
newArr[2].name = 'Tom'
console.log(arr[2].name) // Tom    修改拷贝后的数据会影响原有数据,浅拷贝
  1. 扩展运算符...
let person = {
    name: 'Jack',
    otherInfo: {
        age: 22
    }
}
let newPerson = { ...person }
newPerson.otherInfo.age = 33
console.log(person.otherInfo.age) // 33    修改拷贝后的数据会影响原有数据,浅拷贝
  1. JSON.parse(JSON.stringify())
let person = {
    name: 'Jack',
    otherInfo: {
        age: 22
    }
}
let newPerson = JSON.parse(JSON.stringify(person))
newPerson.otherInfo.age = 33
console.log(person.otherInfo.age) // 22    修改拷贝后的数据不会影响原有数据,深拷贝

可以看出,1~5均为浅拷贝,只有6是深拷贝。但是在遇到函数、undefined 或者symbol 的时候,JSON.parse(JSON.stringify())并不能正常的序列化

// let person = undefined
// let person = Symbol('Jack')
let person = function() {
    console.log('Jack')
}
console.log(JSON.parse(JSON.stringify(person))) // 报错 Uncaught SyntaxError: Unexpected token u in JSON at position 0

自定义深拷贝方法

利用递归,只要某个属性是对象类型,就递归;若是其他类型,则直接复制。代码如下:

function deepCopy(data) {
    if (typeof data !== 'object' || data === null) { // typeof null 的结果是 object
        return data
    }
    let result = Array.isArray(data) ? [] : {}
    for (let key in data) {
        // for...in 会遍历obj原型上的属性,因此需要用hasOwnProperty(key)来判断下当前属性是否属于obj
        if (data.hasOwnProperty(key)) {
            if (typeof data[key] === 'object') {
                result[key] = deepCopy(data[key])
            } else {
                result[key] = data[key]
            }
        }
    }
    return result
}

lodash库的深拷贝方法

_.cloneDeep(value):该函数会递归拷贝value的属性,是深拷贝。
总的来说,对于一般的深拷贝,使用JSON.parse(JSON.stringify())即可,如果遇到特殊的含有函数的对象,则可以自己封装一个深拷贝函数或者使用lodash库的cloneDeep(value)函数。



参考资料:尚硅谷ECMAScript教程(ecmascript详解含es5、es6)

上一篇下一篇

猜你喜欢

热点阅读