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 ]
  • 相关阅读:
    VS2008 环境中完美搭建 Qt 4.7.4 静态编译的调试与发布 Inchroy's Blog 博客频道 CSDN.NET
    编写可丢弃的代码
    c++ using namespace std; 海明威 博客园
    解决MySQL server has gone away
    nginx upstream 调度策略
    (2006, 'MySQL server has gone away') 错误解决 dba007的空间 51CTO技术博客
    Linux IO模型漫谈(2) 轩脉刃 博客园
    redis源码笔记 initServer 刘浩de技术博客 博客园
    MySQLdb批量插入数据
    词库的扩充百度百科的抓取你知道这些热词吗? rabbit9898 ITeye技术网站
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/14113528.html
Copyright © 2011-2022 走看看