javascript实现一个合并多个对象的方法

javascript实现合并对象的方法有很多种,比如:

1、Object.assign

2、jQuery.extend(jQuery也是用javascript写的,谢谢)

3、lodash系列(lodash.merge、lodash.assign等,至于区别自己看文档,文档地址:https://lodash.com/docs)

4、Immutable.js(fackbook打造的一个不可变数据结构JS库)的 merge 方法

其中,Object.assign为javascript原生方法,但是存在以下两个在具体应用场景上的缺点:

1、浏览器兼容性问题

2、只能进行浅合并(关于浅合并深合并,码友之述备矣,这里就不赘言,戳:https://juejin.im/entry/58df4c8b61ff4b006b131792

PS: 之所以说具体应用场景的缺点,是因为假如项目是在高版本浏览器运行,并且只要对数据结构进行浅合并,那就不存在上述两个问题

而为了实现合并对象,特意引入上述的 jQuery、lodash、immutable这些库,就有点夸张了(项目本身需要用到这些库,那当我什么也没说)

好了,进入正题,下面是我自己实现的一个可配置的合并多个对象的方法

function EXT(options) {
    return new EXT.prototype.init(options);
}

EXT.fn = EXT.prototype = {
    type: function(o) {
        return Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
    },
    typeMap: {
        object: function() {
            return {};
        },
        array: function() {
            return [];
        }
    },
    // 默认配置项
    defaults: {
        // 是否深合并
        isDeep: true,
        // 是否遍历合并源对象原型链上的属性
        includePrototype: true,
        // 用于对每个合并项进行自定义修正
        forEach: function(target, name, sourceItem) {
            target[name] = sourceItem;
            return target;
        }
    },
    // 将配置项合并到默认配置项
    init: function(options) {
        for (let name in options) {
            this.defaults[name] = options[name];
        }
        return this;
    },
    merge: function() {
        let self = this,
            _default = self.defaults,
            i = 1,
            length = arguments.length,
            target = arguments[0] || {},
            source,
            targetItem,
            sourceItem,
            tiType,
            siType,
            clone,
            name;

        for (; i < length; i++) {
            // 判断源对象是否为空
            if ((source = arguments[i]) != null) {
                for (name in source) {
                    // 是否遍历源对象的原型链
                    if (source.hasOwnProperty(name) || _default.includePrototype) {
                        targetItem = target[name];
                        sourceItem = source[name];
                        tiType = self.type(targetItem);
                        siType = self.type(sourceItem);

                        // 防止出现回环
                        if (target === sourceItem) {
                            continue;
                        }

                        // 如果复制的是对象或者数组
                        if (_default.isDeep && sourceItem != null && self.typeMap[siType]) {
                            clone = targetItem != null && tiType === siType ? targetItem : self.typeMap[siType]();
                            // 递归
                            target[name] = self.merge(clone, sourceItem);
                        } else {
                            // 处理每一个合并项
                            target = _default.forEach.call(self, target, name, sourceItem);
                        }
                    }
                }
            }
        }
        return target;
    }
};
EXT.fn.init.prototype = EXT.fn;

撸个demo先,先定义两份数据

function Foo() {
    this.a = 1;
}

function Bar() {
    this.c = 3;
}

Foo.prototype.b = 2;
Bar.prototype.d = 4;

let data = {
    info: {
        name: ‘Leslie‘,
        age: 26,
        scores: [60, 66, 70, 80]
    }
};
let data2 = {
    info: {
        name: ‘Leslie‘,
        age: 32,
        scores: [99, 66, 70, {
            name: ‘john‘,
            age: 18
        },
        new Foo()]
    }
};

 1、普通合并

let target = EXT().merge(data1, data2);

结果为:

2、自定义配置进行合并

isDeep:选择是否进行深合并,设置为 false 则只进行浅合并,默认为 true

let target = EXT({ isDeep: false }).merge(data1, data2);
includePrototype:选择是否要遍历对象的原型链,默认为 true
let target = EXT({ includePrototype: false }).merge(data1, data2);

forEach:对每个合并项进行自定义处理

let target = EXT({
    forEach: function(target, name, sourceItem) {
        target[name] = sourceItem + ’hello, 自定义每个合并项‘;
        return target;
    }
}).merge(data1, data2);

好了,这个就是这个方法的使用方法,怎么样?是不是很灵活?是不是很好用?

但是!(最怕的就是但是)这个方法还是有问题的,不知道电视机前的你发现没有,就是合并 new Foo() 的时候,会把 Foo 原型链上的属性一起拷贝到目标对象,而不是拷贝到目标对象的原型链

这个问题暂时没想到解决方法,后面想到会更新上来,或者你有什么解决方案也可以留言,帮忙解决一下,最后祝大家加班愉快!

(胖虎是我偶像)

原文地址:https://www.cnblogs.com/LeslieHoward/p/8544166.html

时间: 2024-10-11 23:13:07

javascript实现一个合并多个对象的方法的相关文章

JS-安全检测JavaScript基本数据类型和内置对象的方法

前言:在前端开发中经常会需要用到检测变量数据类型的需求,比如:判断一个变量是否为undefined或者null来进行下一步的操作,今天在阅读“编写高质量代码-改善JavaScript程序的188个建议”这本书的时候看到这个比较好的方法,在此小记一笔以备在以后的开发中使用. 1:如下所示是我编写的演示代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>I

javascript进击(五)JS对象

JavaScript中是所有事物都是对象.JavaScript允许自定义对象. 对象是带有属性和方法的特殊数据类型. 访问对象的属性: 常见属性 访问对象的方法: 常用方法 (创建JavaScript对象的意义呢,为什么要这么做,有没有可以代替的) 创建JavaScript对象,有两只种方法 1.定义并创建对象的实例: 2.使用函数定义对象,然后就创建新的对象实例. JavaScript数字 不在意小数点,所有的JavaScript数字均为64位,根为10的64位(8比特),浮点数. 精度:整数

Javascript横向/纵向合并单元格TD

在报表系统中,涉及“HTML的TD单元格的合并”恐怕为数不少. 比如,从DB查得数据并经过后台的整理后,可能是这样的: Table1     JOB TOTAL SAL INDEX EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO 1 ANALYST 6000 1 7788 SCOTT ANALYST 7566 4/19/1987 3000.00   20 1 ANALYST 6000 2 7902 FORD ANALYST 7566 12/3/1981

JavaScript中的对象及其方法

1.数组对象: javascript中数组是一种特殊的对象.创建一个新的数组类似于创建一个对象实例,通过new运算符和相应的数组构造函数完成.数组的构造函数是Array(),可以接受多个参数,编写方法如下: var myArray=new Array(); var myArray=new Array("北京","奥运会",100,true);//具有四个元素的数组 var myArray=new Array(5);//创建一个指定元素数量的数组,元素的值是Undef

HTML &amp; CSS &amp; JavaScript 从一个表格到一个灰阶颜色表 03

工具1:HBuilder X 1.9.9.20190522 工具2:火狐浏览器 67.0.4 (64 位) 其实,我还想使用表格,做一个这样的颜色表,如下图所示: 如果按照之前的做法,把每一种颜色都列举出来,估计做完上面这个颜色表,估计人都废了. 为了解决这个重复性的问题,我们必须引入另一种语言:JavaScript 为何学习 JavaScript? JavaScript 是 web 开发者必学的三种语言之一: HTML 定义网页的内容 CSS 规定网页的布局 JavaScript 对网页行为进

HTML &amp; CSS &amp; JavaScript 从一个表格到一个灰阶颜色表 04

工具1:HBuilder X 1.9.9.20190522 工具2:火狐浏览器 67.0.4 (64 位) 目前,我们已经将一些行和列插入到表格中,并设置单元格的背景颜色,显示 RGB 值等. 例 7:最后,我们需要将表头插入到表格中.基于上一个例子,我们再加入一些 JavaScript 代码. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title

Object.assign 合并多个对象的属性,如果是对象有同名属性,则后面对象的属性值覆盖前面的。

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. <script> const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 }; const returnedTarget = Object.assign(target, source); console.log(target); // expected output: Object { a: 1, b: 4, c: 5

使用javascript完成一个简单工厂设计模式。

在JS中创建对象会习惯的使用new关键字和类构造函数(也是可以用对象字面量). 工厂模式就是一种有助于消除两个类依赖性的模式. 工厂模式分为简单工厂模式和复杂工厂模式,这篇主要讲简单工厂模式. 简单工厂模式:使用一个类来生成实例. 复杂工厂模式:使用子类来决定一个成员变量应该是哪个具体的类的实例. 简单工厂模式: 常用对象方法创建和调用 var BallShop = function(){}; BallShop.prototype = { sellBall : function(model){

在JavaScript中重写jQuery对象的方法

jQuery是一个很好的类库,它给我们解决了很多的客户端编程,任何东西都不是万能的,当它不能满足我们的需求时我们需要对它进行重写,同时也不要影响其原有的功能或者修改其原有的功能:我现在的web应用程序大多数时候的数据交互都是通过Ajax来完成的,这样就可以将一些隐藏字段的数据保存在HTML标签的属性中,使HTML标签的代码量减少,如:ID,Timestamp等等,这些不需要用户输入但又不得不提交的字段,通过表单提交的做法是 <input name="ID" value="