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


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 相关文章推荐
jquery学习笔记 用jquery实现无刷新登录
Aug 08 Javascript
javascript使用call调用微信API
Dec 15 Javascript
JavaScript生成的动态下雨背景效果实现方法
Feb 25 Javascript
基于jQuery和CSS3制作数字时钟附源码下载(jquery篇)
Nov 24 Javascript
JavaScript实现搜索框的自动完成功能(一)
Feb 25 Javascript
JavaScript计时器用法分析【setTimeout和clearTimeout】
Jan 18 Javascript
javascript实现二叉树遍历的代码
Jun 08 Javascript
解决Webpack 热部署检测不到文件变化的问题
Feb 22 Javascript
Node.js模拟发起http请求从异步转同步的5种用法
Sep 26 Javascript
JavaScript原型对象原理与应用分析
Dec 27 Javascript
vue从后台渲染文章列表以及根据id跳转文章详情详解
Dec 14 Vue.js
Vue解决移动端弹窗滚动穿透问题
Dec 15 Vue.js
聊聊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 form 表单传参明细研究
2009/07/17 PHP
PHP实现自动登入google play下载app report的方法
2014/09/23 PHP
php flush无效,IIS7下php实时输出的方法
2016/08/25 PHP
Jquery Ajax.ashx 高效分页实现代码
2009/10/20 Javascript
javascript错误的认识不用关心内存管理
2012/12/15 Javascript
在JavaScript中typeof的用途介绍
2013/04/11 Javascript
js一般方法改写成面向对象方法的无限级折叠菜单示例代码
2013/07/04 Javascript
jquery html动态生成select标签出问题的解决方法
2013/11/20 Javascript
JQuery实现table行折叠效果以JSON做数据源
2014/05/26 Javascript
jQuery实现鼠标点击弹出渐变层的方法
2015/07/09 Javascript
js弹出框、对话框、提示框、弹窗实现方法总结(推荐)
2016/05/31 Javascript
浅谈jQuery绑定事件会叠加的解决方法和心得总结
2016/10/26 Javascript
javascript数据结构中栈的应用之符号平衡问题
2017/04/11 Javascript
vue实现百度搜索功能
2020/12/28 Javascript
jQuery实现雪花飘落效果
2020/08/02 jQuery
vue实现一个矩形标记区域(rectangle marker)的方法
2020/10/28 Javascript
vue 导航守卫和axios拦截器有哪些区别
2020/12/19 Vue.js
[44:01]2018DOTA2亚洲邀请赛3月30日 小组赛B组 EG VS paiN
2018/03/31 DOTA
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
Python+OpenCV人脸检测原理及示例详解
2020/10/19 Python
Python使用Selenium+BeautifulSoup爬取淘宝搜索页
2018/02/24 Python
对Python中type打开文件的方式介绍
2018/04/28 Python
python生成密码字典的方法
2018/07/06 Python
Python列表list排列组合操作示例
2018/12/18 Python
Python实现监控Nginx配置文件的不同并发送邮件报警功能示例
2019/02/26 Python
python读取并定位excel数据坐标系详解
2019/06/26 Python
详解pandas使用drop_duplicates去除DataFrame重复项参数
2019/08/01 Python
Python3.7基于hashlib和Crypto实现加签验签功能(实例代码)
2019/12/04 Python
python 实现将小图片放到另一个较大的白色或黑色背景图片中
2019/12/12 Python
Python&amp;&amp;GDAL实现NDVI的计算方式
2020/01/09 Python
Python3 获取文件属性的方式(时间、大小等)
2020/03/12 Python
写自荐信的七个技巧
2013/10/15 职场文书
离职报告范文
2014/11/04 职场文书
2016年秋季新学期致辞
2015/07/30 职场文书
Python面向对象之成员相关知识总结
2021/06/24 Python
vue el-table实现递归嵌套的示例代码
2022/08/14 Vue.js