• 技术文章 >web前端 >js教程

    JavaScript深层克隆对象

    黄舟黄舟2017-02-28 14:24:59原创630

    今天做题看到了深层克隆对象,并且要求在原型链上编程

    于是心血来潮索性来复习一下这个知识点


    克隆对象,这名词看着高大上,其实也没什么,就是拷贝一个长的一模一样的对象
    也许有初学的小伙伴在想,那还不简单么,so easy

    var obj1 = {name: 'payen'};var obj2 = obj1;

    这可并不是克隆对象,obj1和obj2根本就是同一个对象,
    他俩指向同一个内存地址空间
    就好比它们拿到了同样的一个小房子
    这是因为对象是引用值(堆数据)
    说到引用值
    JavaScript中引用值只有对象
    这里注意,数组是特殊的对象,函数也是特殊的可执行对象,
    也就是说,它们也是对象
    所谓深层克隆对象就是说复制一份一模一样的小房子
    不知道我这么说大家能不能理解= ̄ω ̄=
    也就是深层克隆对象引用值需要拷贝,而相对的浅层克隆对象只要把那个引用值拿过来就好了
    不明白不要紧,看完代码就理解了

    浅层克隆对象

    首先来一起看看浅层克隆对象吧

    var house = {
        name: 'payen',
        people: {
            father: true,
            mother: true
        }
    }function easyClone(obj){
        var newObj = {};    for(var prop in obj){        if(obj.hasOwnProperty(prop)){
                newObj[prop] = obj[prop];
            }
        }    return newObj;
    }var newHouse = easyClone(house);

    不要吐槽我用easy,一时想不起来“浅”英文咋说来着(真不知道我英语六级怎么过的)
    关于那个for-in有一个小性能问题,感兴趣的童鞋可以看看我的另一篇文章
    传送门o( ̄▽ ̄)d
    这段代码很简单我就不多解释了
    来看看chrome控制台

    看样子很棒的样子
    那么我现在做一件事
    给新房子加一个人

    看来这个”新房子”并不新啊,不要被变量名字迷惑了
    所以,有引用值出现,浅层克隆并不好用了

    深层克隆对象

    既然如此,我们怎么办呢
    既然要得到新的对象,我们创建一个新对象,把旧对象内部的东西,再拷贝到新对象不就得了
    还有一个问题如果对象里还有对象呢
    那么就继续重复创建添加的过程,很显然是一个循环的过程
    不过循环有两种

    毫无疑问递归更胜一筹
    在递归循环中,遇到满足终止条件的条件时逐层返回来结束
    那么我们就可以通过递归逐层查找引用值,直到没有引用值为止
    还是看代码吧

    var house = {
        name: 'payen',
        people: {
            father: true,
            mother: true,
            child: {
                age: 1
            }
        },
        money: [1000,2000,3000]
    }function deepClone(original, target){
        var target = target || {};// 如果target为undefined或没传参,设置空对象
        for(var prop in original){// 遍历原对象
            if(original.hasOwnProperty(prop)){// 只拷贝对象内部,不考虑原型链
                if(typeof original[prop] === 'object'){// 引用值
                    if(Object.prototype.toString.call(original[prop]) === '[object Array]'){
                        target[prop] = [];// 处理数组引用值
                    }else{
                        target[prop] = {};// 处理对象引用值
                    }// 可以用三目运算符
                    deepClone(original[prop],target[prop]);// 递归克隆
                }else{// 基本值
                    target[prop] = original[prop];
                }   
            }
        }    return target;
    }var newHouse = deepClone(house);

    上面写了那个if-else挺适合用三目运算符的,不过我感觉太冗长了,强迫症表示看了很不舒服
    为了证明它真的深层克隆了,我特意把原始房子变复杂了
    (我们不考虑函数的深层克隆,麻烦并且意义不大)
    这回它真的是新房子了

    我就不展开了
    可以看出来在新对象的引用值改动,旧对象并没有变
    下面我同样实现了原型链上深层克隆对象
    道理是一样的

    var house = {
        name: 'payen',
        people: {
            father: true,
            mother: true,
            child: {
                age: 1
            }
        },
        money: [1000,2000,3000]
    }Object.prototype.cloneTo = function(obj){
        var obj = obj || {};    
        for(var prop in this){        
        if(this.hasOwnProperty(prop)){            
        if(typeof this[prop] === 'object'){                
        if(Object.prototype.toString.call(this[prop]) === '[object Array]'){
                        obj[prop] = [];
                    }else{
                        obj[prop] = {};
                    }                
                    this[prop].cloneTo(obj[prop]);
                }else{
                    obj[prop] = this[prop];
                }
            }
        }    return obj;
    }var newHouse = {};
    house.cloneTo(newHouse);

    以上就是JavaScript深层克隆对象的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:JavaScript 克隆对象
    上一篇:JS区分Object与Aarry方法总结 下一篇:Vue.js框架实现火车票查询系统
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【腾讯云】年中优惠,「专享618元」优惠券!• 18个常见angular面试题(附答案分析)• JavaScript的Symbol类型、隐藏属性及全局注册表详解• 什么是消息队列?node中如何使用消息队列?• 浅析IDEA中如何开发Angular• 整理总结JavaScript常见的BOM操作
    1/1

    PHP中文网