基于对象合并功能的实现示例


Posted in Javascript onOctober 10, 2017

前言

jQuery 中的 $.extend() 是经常使用到工具函数,多用于合并参数(对象),具体用法在这里不过多赘述,可通过传参控制合并过程中是否使用深度拷贝;而ES2015中新增的 Object.assign()方法,也可以实现对象的合并,不过合并过程中使用的是浅拷贝;本文参考了jQuery的extend方法的源码,将自己实现对象合并,即将多个对象的属性复制到目标对象上,若有相同的属性,后面的对象覆盖前面的。

浅拷贝的方式实现对象合并

之前的一篇博文 有专门介绍对象和数组的深浅拷贝,不了解的童鞋请移步。先看实现再解释

function extend() { //extend 浅拷贝实现
  var name,options,copy,
   length = arguments.length,
   i = 1,
   target = arguments[0] || {}; //取目标对象
  
 if(['object','function'].indexOf(typeof target) < 0){
  target = {};
  }
 

  for(;i<length;i++){

  options = arguments[i]

  if(options != null){ //排除空参数的情况 extend({},,)

   for(name in options){ //遍历对象 赋值

   copy = options[name];

   if (copy !== undefined) {
    target[name] = copy;
   }
   }
  }
  }

  return target 
 }

 //测试数据 
 var test1 = {
  a : 1,
  b : {
  c : 2,
  d : 3
  },
  e : [1,'a']
 },
 test2 = {
  b : {
  c : 4,
  d : 5,
  f : 6
  },
  e : [1,'a'],
  g : 7
 }

 var test = extend({},test1,test2);
 console.log(test.b.d); //5

 test2.b.d = 'x'; //修改test2
 console.log(test.b.d); // 'x' test随之修改

思路如下:

1、默认取第一个参数为目标对象,若第一个参数非对象数据类型,则赋值为空对象

2、遍历剩下的参数(源对象),将源对象的属性复制到目标对象上 。

3、返回目标对象为合并的结果

在第二步中没有对源对象的属性值进行判断,所有的全部使用 ‘=' 赋值,所以当源对象的属性值为对象属性时,复制的只是引用值,即为浅拷贝的方式,在测试结果中可以看出 test 和 test2 的 b 属性的属性值,使用的是同一个对象,会互相影响。知道了这些之后,如何实现合并时的深拷贝也应该有思路了。

深度拷贝的方式实现对象合并

需要在复制源对象属性值时,判断值的类型,如果是对象数据类型,则递归调用extend函数。则可以实习深拷贝方式的对象合并,实现如下:

function extend() { //extend 深拷贝实现
  var name,options,src,copy,
   deep = false, //是否深拷贝 默认为false
   length = arguments.length,
   i = 1,
   target = arguments[0] || {};

  //如果第一个参数为boolean类型,赋值给deep
  if(typeof target == 'boolean'){
  deep = arguments[0];
  target = arguments[i] || {}; //目标对象顺延
  i++;
  }

  //如果target不是对象数据类型的话 target赋值为 {}
  if(['object','function'].indexOf(typeof target) < 0){
  target = {};
  }

  for(;i<length;i++){

  options = arguments[i];

  if(options != null){

   for(name in options){

   copy = options[name];
   src = target[name];

   if(target === copy){ //避免重复循环
    continue;
   }

   if(deep && copy && (typeof copy == 'object')){ // 类型判断

    src = Object.prototype.toString.call(copy) == '[object Array]' ? [] : {}; //区分数组和‘对象'
    target[name] = extend(deep,src,copy);
   }else {

    if (copy !== undefined) {

    target[name] = copy;
    }
   }
   }
  }
  }

  return target
 }

1、参数判断,若第一个参数为布尔类型,则取为控制是否深度拷贝的参数deep , deep 默认为false;同时 目标元素会是第二个参数

2、复制属性值时,要判断deep参数和 属性值的类型 ; 若 deep为true 且 属性值为对象类型 则递归调用 extend函数 , 否则直接赋值

3、需要区分 数组 和 ‘对象' ,来给 目标对象的属性赋值不同的初始值。如果都是 {} 的话,数组类型的属性值复制到目标元素上会变为 {'0':xx , '1' : xx ...}

结语

一直都是在直接使用 $.extend(),好用但是不是很清楚其中的实现,自己撸一撸,也许实现上还有不严谨的地方,但是觉得收获还是不错的。

以上这篇基于对象合并功能的实现示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
利用js获取服务器时间的两个简单方法
Jan 08 Javascript
详细讲解JS节点知识
Jan 31 Javascript
登陆成功后自动计算秒数执行跳转
Jan 23 Javascript
javascript基于DOM实现权限选择实例分析
May 14 Javascript
jQuery ajax时间差导致的变量赋值问题分析
Jan 22 Javascript
Bootstrap3 多个模态对话框无法显示的解决方案
Feb 23 Javascript
Vue单页式应用(Hash模式下)实现微信分享的实例
Jul 21 Javascript
在 Node.js 中使用 async 函数的方法
Nov 17 Javascript
对vue中v-on绑定自定事件的实例讲解
Sep 06 Javascript
Node.js实现简单的爬取的示例代码
Jun 25 Javascript
JS实现简易留言板(节点操作)
Mar 16 Javascript
vue-socket.io接收不到数据问题的解决方法
May 13 Javascript
聊聊Vue.js的template编译的问题
Oct 09 #Javascript
Vue组件之全局组件与局部组件的使用详解
Oct 09 #Javascript
Angular2监听页面大小变化的解决方法
Oct 09 #Javascript
JS实现预加载视频音频/视频获取截图(返回canvas截图)
Oct 09 #Javascript
input 标签实现输入框带提示文字效果(两种方法)
Oct 09 #Javascript
详解使用Typescript开发node.js项目(简单的环境配置)
Oct 09 #Javascript
JS中Attr的用法详解
Oct 09 #Javascript
You might like
PHP insert语法详解
2008/06/07 PHP
php 设计模式之 单例模式
2008/12/19 PHP
PHP下对字符串的递增运算代码
2010/08/21 PHP
php+xml编程之SimpleXML的应用实例
2015/01/24 PHP
php利用嵌套数组拼接与解析json的方法
2017/02/07 PHP
在php7中MongoDB实现模糊查询的方法详解
2017/05/03 PHP
PHP设计模式之适配器模式定义与用法详解
2018/04/03 PHP
详解new function(){}和function(){}() 区别分析
2008/03/22 Javascript
小型js框架veryide.librar源代码
2009/03/05 Javascript
jQuery学习7 操作JavaScript对象和集合的函数
2010/02/07 Javascript
$.ajax返回的JSON无法执行success的解决方法
2011/09/09 Javascript
js+CSS实现模拟华丽的select控件下拉菜单效果
2015/09/01 Javascript
JQuery Mobile 弹出式登录框的实现方法
2016/05/28 Javascript
第一篇初识bootstrap
2016/06/21 Javascript
DOM 事件的深入浅出(一)
2016/12/05 Javascript
JavaScript触发onScroll事件的函数节流详解
2016/12/14 Javascript
基于AngularJS实现的工资计算器实例
2017/06/16 Javascript
JavaScript指定断点操作实例教程
2018/09/18 Javascript
JavaScript一元正号运算符示例代码
2019/06/30 Javascript
Vue实现移动端拖拽交换位置
2020/07/29 Javascript
python中numpy基础学习及进行数组和矢量计算
2017/02/12 Python
Python输出各行命令详解
2018/02/01 Python
创建pycharm的自定义python模板方法
2018/05/23 Python
Django实现支付宝付款和微信支付的示例代码
2018/07/25 Python
Python3获取拉勾网招聘信息的方法实例
2019/04/03 Python
python实现根据文件格式分类
2019/10/31 Python
py-charm延长试用期限实例
2019/12/22 Python
django实现更改数据库某个字段以及字段段内数据
2020/03/31 Python
Python绘制动态水球图过程详解
2020/06/03 Python
全面解析CSS Media媒体查询使用操作(推荐)
2017/08/15 HTML / CSS
医院护士求职自荐信格式
2013/09/21 职场文书
小学四年级学生评语
2014/12/26 职场文书
表扬通报怎么写
2015/01/16 职场文书
基于python的matplotlib制作双Y轴图
2021/04/20 Python
html5实现点击弹出图片功能
2021/07/16 HTML / CSS
vue router 动态路由清除方式
2022/05/25 Vue.js