js对象一些使用场景(对象合并、浅拷贝、深拷贝等)

1、对象合并

export function mergeObject(...objs){
    //声明一个空对象
    const result = {};
    //遍历所有的参数对象
    objs.forEach(obj => {
        //获取当前对象所有的属性
        Object.keys(obj).forEach(key => {
            //检测 result 中是否存在 key 属性
            if(result.hasOwnProperty(key)){
                result[key] = [].concat(result[key], obj[key]);
            }else{
                //如果没有 则直接写入
                result[key] = obj[key];
            }
        });
    });
    return result;
}


<script>
        const object = {
            a: [{ x: 2 }, { y: 4 }],
            b: 1,
        }
        const other = {
            a: { z: 3 },
            b: [2, 3],
            c: 'foo'
        }
        console.log(mergeObject(object, other)) 
result:{ a:[ {x:2} , {y:4} , {z:3} ], b:[1,2,3], c:'foo' ]
</script>

2、浅拷贝

浅拷贝:只是复制了对象属性或数组元素本身(只是引用地址值)。修改一个会另一个也会改变
深拷贝:不仅复制了对象属性或者数组元素本身,还复制了指向的对象(使用递归)。每个对象都是一个新的

浅拷贝:


/**
 * 
 * @param {*} target 
 */
export function clone1(target){
    //类型判断  {}  []  null
    if(typeof target === 'object' && target !== null){
        //判断数据是否为数组
        if(Array.isArray(target)){
            return [...target];
        }else{
            return {...target};
        }
    }else{
        return target;
    }
}

/**
 * 
 * @param {*} target 
 */
export function clone2(target){
    //判断
    if(typeof target === 'object' && target !== null){
        //创建一个容器
        const result = Array.isArray(target) ? [] : {};
        //遍历 target 数据
        for(let key in target) {
            //判断当前对象身上是否包含该属性
            if(target.hasOwnProperty(key)){
                //将属性设置到 result 结果数据中
                result[key] = target[key];
            }
        }
        return result;
    }else{
        return target;
    }
}

深拷贝:

deepClone1存在问题:存在一个函数方法关系不能拷贝、属性循环引用不支持
export function deepClone1(target){
    //通过数据创建 JSON 格式的字符串
    let str = JSON.stringify(target);
    //将 JSON 字符串创建为 JS 数据
    let data = JSON.parse(str);
    return data;    
}
deepClone2存在问题:属性循环引用不支持
export function deepClone2(target){
    //检测数据的类型
    if(typeof target === 'object' && target !== null ){
        //创建一个容器
        const result = Array.isArray(target) ? [] : {};
        //遍历对象
        for(let key in target){
            //检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
            if(target.hasOwnProperty(key)){
                //拷贝
                result[key] = deepClone2(target[key]);
            }
        }
        return result;
    }else{
        return target;
    }
}
deepClone:解决上面两种存在的问题,循环引用主要通过创建一个map进行对上个克隆的属性进行缓存处理。
export function deepClone3(target, map=new Map()){
    //检测数据的类型
    if(typeof target === 'object' && target !== null ){
        //克隆数据之前, 进行判断, 数据之前是否克隆过
        let cache = map.get(target);
        if(cache){
            return cache;
        }
        //创建一个容器
        const result = Array.isArray(target) ? [] : {};
        //将新的结果存入到容器中
        map.set(target, result);
        //遍历对象
        for(let key in target){
            //检测该属性是否为对象本身的属性(不能拷贝原型对象的属性)
            if(target.hasOwnProperty(key)){
                //拷贝
                result[key] = deepClone3(target[key], map);
            }
        }
        return result;
    }else{
        return target;
    }
}
deepClone4:最优化的代码
export function deepClone4(target, map=new Map()){
    //检测数据的类型
    if(typeof target === 'object' && target !== null ){
        //克隆数据之前, 进行判断, 数据之前是否克隆过
        let cache = map.get(target);
        if(cache){
            return cache;
        }
        //判断目标数据的类型
        let isArray = Array.isArray(target);
        //创建一个容器
        const result = isArray ? [] : {};
        //将新的结果存入到容器中
        map.set(target, result);
        //如果目标数据为数组
        if(isArray){
            //forEach 遍历
            target.forEach((item, index) => {
                result[index] = deepClone4(item, map);
            });
        }else{
            //如果是对象, 获取所有的键名, 然后 forEach 遍历
            Object.keys(target).forEach(key => {
                result[key] = deepClone4(target[key], map);
            });
        }
        return result;
    }else{
        return target;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容