• Js实现深浅复制


    为什么有深复制、浅复制?

    JavaScript中有两种数据类型,基本数据类型如undefined、null、boolean、number、string,另一类是Object。简单数据类型只存储在内存中的栈区,复制的时候是值传递给新的索引。而复杂数据类型由栈区和堆区共同储存,栈区执行同样的操作,只是把堆地址复制了一份,而真实数据在堆区中依然只有一份。
    为了不影响原有数据,那么我们就新建一个对象,遍历原有对象的属性赋值到新属性。

    let newObj = {}
    for (let prop in obj) {
      newObj[prop] = obj[prop]
    }

    上面这个循环也可以用Object.assign({}, obj);来实现。
    这样做是否解决问题?未必,因为Object中可以嵌套Object,如果原有对象属性中有复杂数据类型,那么新的对象中也只能得到一个地址。这种情况被称为浅复制。我们希望能将对象中的对象,无论多少层,都能复制一份,能达到这种效果的,称为深复制

    深复制的几种方法

    首先假设有数据

    let obj = {
        a: 23,
        b: [0, 1, [2, 3], function() {console.log('in array')}, undefined],
        c: {k: 'value'},
        d: function() {console.log('a')}
        }

    jsON.parse(jsON.stringify(obj))

    let newObj = JSON.parse(JSON.stringify(obj))
    newObj.newKey = 'newValue'
    console.log(obj)
    console.log(newObj)

    如果处理对象只是简单的键值对,这个方法效果不错。

    这个方法的缺点

    • 无法复制函数
    • 忽略undefined值
    • 无法处理Set、Map、Symbol类型(即使用上repalce参数)
    • 原有的原型链会消失
    • 循环引用的对象会报错

    递归法

    因为要处理属性的值也是Object这种情况,自然可以想到递归这种处理方法。

    function deepCopy(oldObj, newObj) {
        let obj = newObj || {} 
        for (let i in oldObj) {
            if (oldObj[i] === obj) { // 防止循环引用
                continue
            }
    
            if (typeof oldObj[i] === 'object') {
                // obj[i] = (oldObj[i].constructor === Array) ? [] : {}
                obj[i] = oldObj[i] instanceof Array ? [] : {}
                deepCopy(oldObj[i], obj[i])
            } else {
                obj[i] = oldObj[i]
            }
        }
        return obj;
    }

    这样就能处理一个嵌套了Object和Array等复杂变量的对象。但是对象中还可能包含Date和RegExp对象、Set、Map……

    Lodash库

    const lodash = require('lodash')
    let newObj = lodash.cloneDeep(obj)

    资源搜索网站大全 https://www.renrenfan.com.cn 广州VI设计公司https://www.houdianzi.com

    数组的复制

    let arr = [1, 2, 3, [4, 5], {a: 1}]
    
    let copy = arr
    copy.push(6)
    
    let copy1 = [...arr]
    copy1.push(999)
    
    let copy2 = Array.from(arr)
    copy2.push(888)
    
    let copy3 = arr.slice()
    copy3.push(777)
    
    // 以上方法都是浅拷贝
    arr[4].a = 2
    
    console.log(arr)   // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6 ]
    console.log(copy1) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6 ]
    console.log(copy2) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 888 ]
    console.log(copy3) // [ 1, 2, 3, [ 4, 5 ], { a: 2 }, 6, 777 ]
  • 相关阅读:
    linux安装nginx
    git配置多个SSH密钥
    webpack加载器安装node-sass失败的解决方法
    Vue-cli webpack打包之后index.html缺少引号的问题
    算法:一个数组中所有元素的最小公倍数
    JS 实现一个睡眠函数sleep
    剑指offer 牛客67道题集合
    剑指offer
    剑指offer
    剑指offer
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/14113528.html
Copyright © 2020-2023  润新知