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


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 相关文章推荐
网页设计常用的一些技巧
Dec 22 Javascript
jquery创建一个新的节点对象(自定义结构/内容)的好方法
Jan 21 Javascript
JQuery动画和停止动画实例代码
Mar 01 Javascript
jquery实现图片翻页效果
Dec 23 Javascript
jquery制作LED 时钟特效
Feb 01 Javascript
js自定义QQ菜单效果
Jan 10 Javascript
jQuery实现鼠标跟随效果
Feb 20 Javascript
原生JS实现N级菜单的代码
May 21 Javascript
JavaScript的数据类型转换原则(干货)
Mar 15 Javascript
微信小程序学习笔记之函数定义、页面渲染图文详解
Mar 28 Javascript
js实现详情页放大镜效果
Oct 28 Javascript
TypeScript中条件类型精读与实践记录
Oct 05 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+DBM的同学录程序(3)
2006/10/09 PHP
关于zend studio 出现乱码问题的总结
2013/06/23 PHP
php通过分类列表产生分类树数组的方法
2015/04/20 PHP
php文件压缩之PHPZip类用法实例
2015/06/18 PHP
php操作路径的经典方法(必看篇)
2016/10/04 PHP
php实现的SSO单点登录系统接入功能示例分析
2016/10/12 PHP
php 多个变量指向同一个引用($b = &amp;$a)用法分析
2019/11/13 PHP
3Z版基于jquery的图片复选框(asp.net+jquery)
2010/04/12 Javascript
深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解
2013/05/08 Javascript
Node.js开发之访问Redis数据库教程
2015/01/14 Javascript
js实现模拟银行卡账号输入显示效果
2015/11/18 Javascript
JS禁用页面上所有控件的实现方法(附demo源码下载)
2015/12/17 Javascript
JavaScript仿微信(电话)联系人列表滑动字母索引实例讲解(推荐)
2017/08/16 Javascript
利用Dectorator分模块存储Vuex状态的实现
2019/02/05 Javascript
简单实现vue中的依赖收集与响应的方法
2019/02/18 Javascript
vue项目中引入Sass实例方法
2019/08/27 Javascript
Element-ui el-tree新增和删除节点后如何刷新tree的实例
2020/08/31 Javascript
OpenLayers3实现地图显示功能
2020/09/25 Javascript
[02:56]《DAC最前线》之国外战队抵达上海备战亚洲邀请赛
2015/01/28 DOTA
Python的类实例属性访问规则探讨
2015/01/30 Python
python+django加载静态网页模板解析
2017/12/12 Python
python pandas中对Series数据进行轴向连接的实例
2018/06/08 Python
python提取log文件内容并画出图表
2019/07/08 Python
Django中使用CORS实现跨域请求过程解析
2019/08/05 Python
python百行代码自制电脑端网速悬浮窗的实现
2020/05/12 Python
Html5 Geolocation获取地理位置信息实例
2016/12/09 HTML / CSS
HTML5拍照和摄像机功能实战详解
2019/01/24 HTML / CSS
电脑饰品店的创业计划书
2014/01/21 职场文书
国际贸易毕业生求职信
2014/07/20 职场文书
安全伴我行演讲稿
2014/09/04 职场文书
2014三年级班主任工作总结
2014/12/05 职场文书
2014年政协工作总结
2014/12/09 职场文书
2014年检察院个人工作总结
2014/12/09 职场文书
元旦联欢晚会主持词
2015/07/01 职场文书
祝寿主持词
2015/07/02 职场文书
OpenCV-Python模板匹配人眼的实例
2021/06/08 Python