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

初探浅拷贝&深拷贝

作者: 林键燃 | 来源:发表于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的深拷贝
深拷贝与浅拷贝的区别,实现深拷贝的几种方法

相关文章

  • 初探浅拷贝&深拷贝

    思考 这个代码为什么具有深拷贝作用 浅拷贝与深拷贝 在JavaScript中,对于Object和Array这类引用...

  • 浅谈Java的深拷贝与浅拷贝的雷区

    深拷贝与浅拷贝初探 先说说浅拷贝... 一个类的拷贝构造方法通常实现为成员变量逐域赋值,即将当前对象的各个成员变量...

  • iOS深拷贝(MutableCopy)与浅拷贝(Copy)的区别

    深拷贝和浅拷贝的概念 iOS中有深拷贝和浅拷贝的概念,那么何为深拷贝何为浅拷贝呢?浅拷贝:浅拷贝并不拷贝对象本身,...

  • 深拷贝 & 浅拷贝

    浅拷贝:大多数对象都引用(指向)其他对象,不复制引用对象。新复制的对象只指向现有的引用对象。 例如 NSArray...

  • 深拷贝&浅拷贝

    数据保存到对象以后会涉及到拷贝的问题,而数据保存的格式多样,这就涉及到了深拷贝和浅拷贝的问题。产生的原因: 用以上...

  • 浅拷贝&深拷贝

  • iOS - copy 与 mutableCopy

    一说到拷贝,就不得不提浅拷贝和深拷贝。 何谓浅拷贝?何谓深拷贝? 往简单的说: 浅拷贝:拷贝地址。 深拷贝:拷贝内...

  • iOS面试题-第二页

    11.深拷贝和浅拷贝的理解. 深拷贝;拷贝的内容. 浅拷贝:拷贝的指针. 深拷贝如: NSMutableDicti...

  • js浅拷贝深拷贝

    js浅拷贝,深拷贝的简单实现 基础数据 浅拷贝 深拷贝

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

网友评论

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

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