js中合并多个对象的方法

28,825 阅读3分钟

1.利用assign合并多个对象,第一个参数为目标对象,后面可以有多个源对象。

  • 首先我们需要知道的是assign实行的是浅拷贝,也就是说如果源对象的某个属性值是对象,那么assign拷贝的是它的引用。
  • assign是将源对象的可枚举属性复制到目标对象,如果属性名相同后面的属性会覆盖前面属性,只有一个参数assign会直接返回该参数。
  • 如果参数不是对象,assign会先将其转为对象,再进行操作
  • assign可以处理数组,但数组会被视为对象

        let obj1 = {
            name: 'dk',
            age: '99',
            feature: 'stronge'
        }
    
        let obj2 = {
            name: 'tk',
            age: '99',
            feature1: 'noStronge',
            address: {
                city: '广州',
                address: {
                city: '深圳'
                }
            },
            skills: ['JavaScript', 'React', 'Node']
        }
    
        let res = Object.assign(obj1, obj2);
        res.address.address.city = '广州';
        console.log(obj2);
        console.log(res);

2.利用扩展运算符

需要注意的是利用扩展运算符...合并对象 同样是进行浅拷贝

        let obj1 = {
            name: 'dk',
            age: '99',
            feature: 'stronge'
        }
    
        let obj2 = {
            name: 'tk',
            age: '99',
            feature1: 'noStronge',
            address: {
                city: '广州',
                address: {
                city: '深圳'
                }
            },
            skills: ['JavaScript', 'React', 'Node']
        }
    
        let res = {...obj1, ...obj2};
        res.address.address.city = '杭州';
        console.log(obj2);
        console.log(res);

3.手写函数(浅拷贝实现)

        let merger = (...opts) => {
            let res = {};
            
            let combine = (opt) => {
                for(let prop in opt) {
                    if(opt.hasOwnProperty(prop)) {
                        res[prop] = opt[prop];
                    }
                }
            }
    
            //扩张运算符将两个对象合并到一个数组里,因此opts可以调用length方法
            for (let i = 0; i < opts.length; i++) {
                combine(opts[i]);
            }
            return res;
        }


        let obj1 = {
            name: 'dk',
            age: '99',
            feature: 'stronge'
        }
    
        let obj2 = {
            name: 'tk',
            age: '99',
            feature1: 'noStronge',
            address: {
                city: '广州',
                address: {
                city: '深圳'
                }
            },
            skills: ['JavaScript', 'React', 'Node']
        }
    
        let res = merger(obj1, obj2);
    
        //查看是否是浅拷贝
        res.address.address.city = '杭州';
        console.log(res);
        console.log(obj2);

上面实现的函数主要的知识点有

Object对象的hasOwnProperty方法,主要用于判断实例对象是否有该属性。

for in循环主要用于遍历对象属性。不管是自身的还是继承的属性。

  • 既然说到for in,顺便提一下for of 与for in的区别
    • 先说结论,for in 一般用于遍历对象属性,for of 一般用于遍历数组。
    • 官方文档给的解释是for in 用于循环一个可枚举对象,for of用于可迭代对象,可枚举对象和可迭代对象之间的关系就是:可枚举对象视为矩形,可迭代对象视为正方形。因此,所有可迭代对象都是可枚举对象,但并非所有可枚举都是可迭代对象。它们之间的关系就和矩形和正方形之间差不多。
    • 用object来说的话,for in遍历的是key,for of 遍历的是value,但是js中的object用for of会直接报错。

4.手写函数(实现深拷贝)

下面实现深拷贝的函数思路和浅拷贝差不多,就是多出了一个递归,如果有不了解递归的小伙伴,可以去了解一下。

        let merger = (...opts) => {
            let res = {};
            
            let combine = (opt) => {
                for(let prop in opt) {
                    if(opt.hasOwnProperty(prop)) {
    
                        //下面是深拷贝与浅拷贝的区别,用到了递归的思想
                        if(Object.prototype.toString.call(opt[prop]) === '[object Object]') {
    
                            res[prop] = merger(res[prop], opt[prop]);
    
                        }else {
    
                            res[prop] = opt[prop];
    
                        }
                        
                    }
                }
            }
    
            //扩张运算符将两个对象合并到一个数组里因此可以调用length方法
            for (let i = 0; i < opts.length; i++) {
                combine(opts[i]);
            }
            return res;
        }


        let obj1 = {
            name: 'dk',
            age: '99',
            feature: 'stronge'
        }
    
        let obj2 = {
            name: 'tk',
            age: '99',
            feature1: 'noStronge',
            address: {
                city: '广州',
                address: {
                city: '深圳'
                }
            },
            skills: ['JavaScript', 'React', 'Node']
        }
    
        let res = merger(obj1, obj2);
    
        //查看是否是浅拷贝
        res.address.address.city = '杭州';
        console.log(obj2);
        console.log(res);

上面代码的知识点有

  • Object.prototype.toString.call() 用于判断类型,他其实是toString( )方法和call( )方法结合使用,toString( ) 方法用于返回对象类型字符串,而call( )方法就是绑定this嘛。
  • 上面在merger中调用merger就是递归的思想,有兴趣的小伙伴可以去学学递归的思想。

5.最后介绍最后一种办法Lodash's中的merge( )方法。Lodash's是node中的库。它也是一种深拷贝的办法。

    const _ = require('lodash');
    
    let obj1 = {
        name: 'dk',
        age: '99',
        feature: 'stronge'
    }
    
    let obj2 = {
        name: 'tk',
        age: '99',
        feature1: 'noStronge',
        address: {
            city: '广州',
            address: {
            city: '深圳'
            }
        },
        skills: ['JavaScript', 'React', 'Node']
    }
    
    const res = _.merge(obj1, obj2);
    console.log(res);