美文网首页
JavaScript深浅拷贝

JavaScript深浅拷贝

作者: 麦西的西 | 来源:发表于2021-02-17 19:18 被阅读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)

    相关文章

      网友评论

          本文标题:JavaScript深浅拷贝

          本文链接:https://www.haomeiwen.com/subject/lazvphtx.html