多种浅拷贝和深拷贝写法

浅拷贝

数组浅拷贝 Array.prototype.concat()
// concat() 方法用于连接两个或多个数组。
// 该方法不会改变现有的数组,而是返回一个新的数组
constnewArr=arr.concat()
数组浅拷贝 Array.prototype.slice()
// slice() 方法可从已有的数组中返回选定的元素
// 注意: slice() 方法不会改变原始数组,而是返回一个新的数组
constnewArr=arr.slice()
对象浅拷贝 Object.assign()
// Object.assign() 方法可以将任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象
constnewObj=Object.assign({}, obj)
扩展运算符 ...
// 数组
constnewArr= [...arr];
// 对象
constnewObj= [...obj];
for in 浅拷贝
const_shallowClone=target=> {
    // 基本数据类型直接返回
    if (typeoftarget==='object'&&target!==null) {
        // 获取target的构造体
        constconstructor=target.constructor
        // 构造体为以下类型直接返回
        if (/^(Function|RegExp|Date|Map|Set)$/i.test(constructor.name)) returntarget
        // 判断是否是一个数组
        constcloneTarget=Array.isArray(target) ? [] : {}
        for (constkeyintarget) {
            // 只拷贝其自身的属性
            if (target.hasOwnProperty(key)) {
                cloneTarget[key] =target[key]
            }
        }
        returncloneTarget
    } else {
        returntarget
    }
​
}

深拷贝

JSON.parse(JSON.stringify(obj))
不能拷贝函数和undefined, 日期,正则

constnewData=JSON.parse(JSON.stringify(data))

递归深拷贝

/**
  * 深拷贝简化版
  * @param {any} target
  * @param {WeakMap} map
  * @returns {any} cloneTarget
  */
const_completeDeepClone= (target, map=newWeakMap()) => {
    // 基本数据类型,直接返回
    if (typeoftarget!=='object'||target===null) returntarget
    // 函数 正则 日期 ES6新对象,执行构造题,返回新的对象
    constconstructor=target.constructor
    if (/^(Function|RegExp|Date|Map|Set)$/i.test(constructor.name)) returnnewconstructor(target)
    // map标记每一个出现过的属性,避免循环引用
    if (map.get(target)) returnmap.get(target)
    map.set(target, true)
    constcloneTarget=Array.isArray(target) ? [] : {}
    for (propintarget) {
        if (target.hasOwnProperty(prop)) {
            cloneTarget[prop] =_completeDeepClone(target[prop], map)
        }
    }
    returncloneTarget
}
/**
  * 深拷贝加强版
  * @param {any} parent
  * @returns {any} child
  */
exportconstclone=parent=> {
    // 判断类型
    constisType= (obj, type) => {
        if (typeofobj!=="object") returnfalse;
        consttypeString=Object.prototype.toString.call(obj);
        letflag;
        switch (type) {
            case"Array":
                flag=typeString==="[object Array]";
                break;
            case"Date":
                flag=typeString==="[object Date]";
                break;
            case"RegExp":
                flag=typeString==="[object RegExp]";
                break;
            case"Set":
                flag=typeString==="[object Set]";
                break;
            case"Map":
                flag=typeString==="[object Map]";
                break;
            default:
                flag=false;
        }
        returnflag;
    };
​
    // 处理正则
    constgetRegExp=re=> {
        varflags="";
        if (re.global) flags+="g";
        if (re.ignoreCase) flags+="i";
        if (re.multiline) flags+="m";
        returnflags;
    };
    // 维护储存循环引用的对象
    constcached=newWeakMap;
​
    const_clone=parent=> {
        if (parent===null) returnnull;
        if (typeofparent!=="object") returnparent;
​
        // 循环引用则直接返回
        if (cached.get(parent)) returncached.get(parent)
​
        letchild, proto;
​
        if (isType(parent, "Array")) {
            // 对数组做特殊处理
            child= [];
        } elseif (isType(parent, "RegExp")) {
            // 对正则对象做特殊处理
            child=newRegExp(parent.source, getRegExp(parent));
            if (parent.lastIndex) child.lastIndex=parent.lastIndex;
        } elseif (isType(parent, "Date")) {
            // 对Date对象做特殊处理
            child=newDate(parent.getTime());
        } elseif (isType(parent, "Set")) {
            // 对Set对象做特殊处理
            child=newSet();
            parent.forEach(val=> {
                child.add(_clone(val))
            })
        } elseif (isType(parent, "Map")) {
            // 对Map对象做特殊处理
            child=newMap();
            parent.forEach((val, key) => {
                child.set(key, _clone(val))
            })
        } else {
            // 处理对象原型
            proto=Object.getPrototypeOf(parent);
            // 利用Object.create切断原型链
            child=Object.create(proto);
        } 
        cached.set(parent, child)
​
        for (letiinparent) {
            // 递归
            child[i] =_clone(parent[i]);
        }
​
        returnchild;
    };
    return_clone(parent);
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值