zoukankan      html  css  js  c++  java
  • JavaScript中的深拷贝和浅拷贝

    1、概念

      ECMAScript中的变量有两种类型:基本类型值和引用类型值。基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置,基本类型值有Number、String、Boolean、Null、Undefined、Symbol。引用类型值指的是那些保存在堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象,引用类型值有Object、Array、Function等。

      深拷贝和浅拷贝只存在引用类型值中。

      浅拷贝类似于将一个对象obj1赋值给一个变量obj2,赋值后obj1和obj2指向同一个内存地址,修改其中一个会影响另外一个(浅拷贝时对象只会被拷贝最外部的一层,至于更深层的对象,则依然是通过引用指向同一块堆内存.)。深拷贝则是在内存中的另外一个地址创建一个对象obj3,除了指针指向的内存位置不同,obj3与obj1完全相同,obj3独立于obj1,操作一个对象时不会对另一个对象造成影响。。

    2、深拷贝探究

      2-1、 Array

      Array的slice()、concat()、Array.from()方法只能实现一维数组的深拷贝,对二维及以上数组就无法深拷贝了。

      Eg: [1, 2, 3, 'a']可以实现深拷贝,[1, 2, 3, [4, 5]]无法实现深拷贝。

      2-2、Objec

      Object.assign()方法只能实现一维对象的深拷贝,对二维及以上对象无法进行深拷贝。

      Eg: {x: 1, y: 1}能实现深拷贝, {x: 1, y: {m: 2}}无法实现深拷贝。

      2-3:、JSON.parse(JSON.stringify(obj)):

      能实现一些比较简单的深拷贝,但是缺陷比较明显:当Object或Array中有值为undefined、所有函数及Symbol时,JSON.stringify(obj)将Object序列化时会忽略这些值,JSON.stringify(obj)将Array序列化时会将这些值转换为null。但是该方法足以应对比较简单的不含有上述值的对象。

      2-4:JavaScript自身提供的方法不足以解决深拷贝的问题,所以需要借助其他方法。其一是递归函数,其二是使用第三方库,如jQuery的$.extendlodash的_.deepCopy方法

      2-5、递归方法:

    function deepCopy(obj) {
        // 创建一个新对象
        let result = {}
        let keys = Object.keys(obj),
            key = null,
            temp = null;
    
        for (let i = 0; i < keys.length; i++) {
            key = keys[i];    
            temp = obj[key];
            // 如果字段的值也是一个对象则递归操作
            if (temp && typeof temp === 'object') {
                result[key] = deepCopy(temp);
            } else {
            // 否则直接赋值给新对象
                result[key] = temp;
            }
        }
        return result;
    }
    
    var obj1 = {
        x: {
            m: 1
        },
        y: undefined,
        z: function add(z1, z2) {
            return z1 + z2
        },
        a: Symbol("foo")
    };
    
    var obj2 = deepCopy(obj1);
    obj2.x.m = 2;
    
    console.log(obj1); //{x: {m: 1}, y: undefined, z: ƒ, a: Symbol(foo)}
    console.log(obj2); //{x: {m: 2}, y: undefined, z: ƒ, a: Symbol(foo)}

    // 代码出自掘金的一篇博文,链接:https://juejin.im/post/5ad5b908f265da23870f540d

      

  • 相关阅读:
    再读《赤壁赋》念《滕王阁序》
    赤壁赋
    关于C语言中的位域
    Eliot
    cnblogs.com博客园简介
    springboot+thymeleaf 实现图片文件上传及回显
    绑定事件的方式
    无法获得 VMCI 驱动程序的版本: 句柄无效。
    Connection is read-only解决方式
    Java 线程的 5 种状态
  • 原文地址:https://www.cnblogs.com/zhengxj1991/p/9854949.html
Copyright © 2011-2022 走看看