美文网首页
初探浅拷贝&深拷贝

初探浅拷贝&深拷贝

作者: 林键燃 | 来源:发表于2018-10-09 09:12 被阅读121次

    思考

    这个代码为什么具有深拷贝作用

    obj = JSON.parse(JSON.stringify(deepCloneObj));
    

    浅拷贝与深拷贝

    在JavaScript中,对于Object和Array这类引用类型值,当从一个变量向另一个变量复制引用类型值时,这个值的副本其实是一个指针,两个变量指向同一个堆内存中的对象,改变其中一个变量,另一个也会受到影响。

    这种拷贝分为两种情况:拷贝引用和拷贝实例,也就是我们说的浅拷贝和深拷贝

    浅拷贝

    将原对象/数组的引用直接赋给新对象/数组,新对象/数组只是原对象/数组的一个引用

    深拷贝

    创建一个新的对象/数组,将原对象的各项属性的“值”(数组的所有元素拷贝过来),是“值”而不是“引用”

    实例1:利用 parse() 方法和 stringify() 方法实现对一个对象的深拷贝。

    stringify() 方法可以将一个JS对象序列化一个JSON字符串,parse()方法可以将JSON字符串反序列化为一个JS对象。通过这两个方法可以实现对象的深拷贝。

    function deepClone(obj) {
        return JSON.parse(JSON.stringify(obj))
    }
    const obj = {
        arr: ['a', 'n', 'd'],
        number: 1,
        obj: {
            name: 'Aranl',
            age: 18
        },
        func: function() {
            return 'ok'
        }
    }
    const objClone = deepClone(obj)
    console.log(objClone) // => 
    /*
        [object Object] {
          arr: ["a", "n", "d"],
          number: 1,
          obj: [object Object] {
            age: 18,
            name: "Aranl"
          }
        }
    */
    

    在上面的例子中,我们可以看出,原对象的方法在拷贝的过程中丢失了,原因是在序列化JS对象的过程中,所有的函数和原型成员会被有意的忽略。

    实例2:利用 parse() 方法和 stringify() 方法实现将一个或者或多个对象深拷贝到目标对象中
    /**
     * 对传入一个目标对象和一个对象或多个对象进行深拷贝操作,若属性相同,则取用后面对象的值
     * 返回深拷贝操作后的对象
     * @param { Object } target
     * @param 一个或多个 { Object } sources
     * @return { Object } target
     */
    function deepCloneObjects(target, ...sources) {
     sources.forEach(src=>{
       for(let key in src) {
         if(typeof src[key] === 'object') {
           target[key] = JSON.parse(JSON.stringify(src[key]))
         }else {
           target[key] = src[key]
         }
       }
     })
     return target
    }
    
    实例3: 通过递归的方式,实现对一个对象进行深拷贝
        /**
         * 使用for in拷贝对象、数组 可拷贝方法
         * @param {object} obj 拷贝模式
         * @returns {array, object} 返回拷贝后的数组、对象
         */
        function deepClone(obj) {
            let temp = Array.isArray(obj) ? [] : {}
            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    if (obj[key] && typeof obj[key] === 'object') {
                        temp[key] = deepClone(obj[key])
                    } else {
                        temp[key] = obj[key]
                    }
                }
            }
            return temp
        }
        
        let obj = [1,2,{m:1}]
        let deepCloneObj = deepClone(obj)
        deepCloneObj.push(3)
        console.log(obj, deepCloneObj)
    
    实例4: 通过递归的方式,实现对一个或者多个对象深拷贝
    /**
     * 对传入一个对象进行深拷贝操作,多个对象进行深拷贝“merge”操作
     * 返回深拷贝“merge”操作后的对象
     *
     * @param 一个或多个 { Object } obj
     * @return { Object } obj
     */
     
    function mergeObj() {
        const _copy = (obj1,obj2) => {
            const _obj = Object.assign({}, obj1);
            for (const key in obj2) {
                const type1 = toString.call(_obj[key])
                const type2 = toString.call(obj2[key])
                if (type1 === type2 && type2 === '[object Array]') {
                    _obj[key] = _obj[key].concat(obj2[key])
                } else if (type1 === type2 && type2 === '[object object]') {
                    _obj[key] = _copy(_obj[key], obj2[key])
                } else {
                    _obj[key] = obj2[key]
                }
            }
            return _obj
        }
        
        const _args = Object.assign({}, arguments)
        let _len = Object.keys(_args).length
        while (_len-- > 0) {
            _args[_len - 1] = _copy(_args[_len - 1], _args[_len]);
        }
        return _args[0]
    }
    

    参考链接

    JavaScript中的浅拷贝和深拷贝
    详解JavaScript的深拷贝
    深拷贝与浅拷贝的区别,实现深拷贝的几种方法

    相关文章

      网友评论

          本文标题:初探浅拷贝&深拷贝

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