zoukankan      html  css  js  c++  java
  • 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 ]
  • 相关阅读:
    SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
    谷歌浏览器扩展程序manifest.json参数详解
    获取天气api
    UVA 10385 Duathlon
    UVA 10668 Expanding Rods
    UVALIVE 3891 The Teacher's Side of Math
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 11210 Chinese Mahjong
    UVA 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/14113528.html
Copyright © 2011-2022 走看看