• JavaScript深拷贝浅拷贝全析


    浅拷贝

    用浅拷贝如果改变obj2的对象,obj1不会再改变,它们不会引用一个值,但如果对象里面还有对象,就会失效,它们是同一个引用。

    方法1:用Object.create克隆对象

    方法2:数组用concat

    方法3:对象用assign

    方法4:扩展运算符(...)

    方法1:用Object.create克隆对象

    用法:

    var obj1 = {a:2,b:{name:'小明'}};
    var obj2 = Object.create(obj1);
    
    

    详解:

    var obj1 = {a:2,b:{name:'小明'}};
    var obj2 = Object.create(obj1);
    obj2.a = 3;
    obj2.b.name = '小红';
    console.log(obj1,obj2);
    

    结果:

    image

    结论:

    obj1对象中的一级对象a:2并没有受影响,但二级对象b已经受影响。所以Object.create克隆的对象也只能实现一级对象的深拷贝

    方法2:数组用concat

    用法:

    [].concat(arr)
    

    详解:

    var arr = [{id:1,name:'1',other:{sex:'男'}}]
    var brr = [].concat(arr);
    brr[0].id = 2;
    brr[0].other.sex = '女';
    console.log(arr[0],brr[0])
    

    结果:

    image

    结论:

    arr的一级对象(id)和对象里面的对象(other.sex)都是引用同一个指针,不能实现深拷贝。

    方法3:对象用assign

    用法:

    var obj1 = {a: 1}
    var obj2 = Object.assign({}, obj1)
    

    详解:

    var obj = {id:1,name:{a:'xx'},fn:function(){},un:undefined};
    var obj2 = Object.assign({}, obj);
    obj2.id = 2;
    obj2.name.a = 'obj2';
    console.log(obj,obj2)
    

    结果:

    image

    结论:

    obj的一级对象(id)的确不受影响,但对象里面的对象(name.a)还是引用同一个指针,不能实现深拷贝。

    方法4:扩展运算符(...)

    用法:

    var obj1 = {a: 1}
    var obj2 = {...obj1}
    

    详解:

    var obj = {id:1,name:{a:'xx'},fn:function(){},un:undefined};
    var obj2 = {...obj};
    obj2.id = 2;
    obj2.name.a = 'obj2';
    console.log(obj,obj2)
    

    结果:

    image

    结论:

    obj的一级对象(id)的确不受影响,但对象里面的对象(name.a)还是引用同一个指针,不能实现深拷贝。

    深拷贝

    方法1:JSON.parse(JSON.stringify())

    方法2:MessageChannel

    方法3:lodash.cloneDeep

    用深拷贝的话,就算对象里面还有对象,也不会是同一个引用,但是会忽略undefinedfunction,用方法3不会忽略functionundefined

    方法1:JSON.parse(JSON.stringify())

    var obj1 = {a: 1}
    obj2 = JSON.parse(JSON.stringify(obj1))
    

    方法2:MessageChannel

    var obj = {id:1,name:{a:'xx'}};
    
    function structuralClone(obj) {
        return new Promise((resolve) => {
            const {port1, port2} = new MessageChannel();
            port2.onmessage = ev => resolve(ev.data);
            port1.postMessage(obj);
        })
    }
    structuralClone(obj).then(res=>{
        console.log(res);
        var obj3 = res;
        obj3.name.a = 'obj3';
        console.log(obj,obj3);
    })
    
    <!-- 用promise是为了好传数据 -->
    

    image

    方法3:lodash.cloneDeep

    import _ from 'lodash'
    var obj = {id:1,name:{a:'xx'},fn:function(){},un:undefined};
    var obj2 = _.cloneDeep(obj);
    obj2.name.a = 'obj2';
    console.log(obj,obj2)
    

    image

  • 相关阅读:
    整理+学习《骆昊-Java面试题全集(下)》
    整理+学习《骆昊-Java面试题全集(中)》
    Linux专家心目中的最佳Linux发行版有哪些?
    常用的Git Tips
    Python 3 加密简介
    LXD 2.0 系列(一):LXD 入门
    英特尔构建云集成编排工具
    Unix操作系统中UUCP知识详细讲解
    Windows 的 AD 域寄生于 Linux 机器
    Git秘籍:在 Git 中进行版本回退
  • 原文地址:https://www.cnblogs.com/firefly-pengdan/p/13409193.html
Copyright © 2020-2023  润新知