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


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 相关文章推荐
IE6下JS动态设置图片src地址问题
Jan 08 Javascript
js 延迟加载 改变JS的位置加快网页加载速度
Dec 11 Javascript
js获取上传文件大小示例代码
Apr 10 Javascript
推荐8款jQuery轻量级树形Tree插件
Nov 12 Javascript
Javascript中数组sort和reverse用法分析
Dec 30 Javascript
jQuery的ajax下载blob文件
Jul 21 Javascript
AngularGauge 属性解析详解
Sep 06 Javascript
Thinkjs3新手入门之添加一个新的页面
Dec 06 Javascript
详解JSON.stringify()的5个秘密特性
May 26 Javascript
js实现从右往左匀速显示图片(无缝轮播)
Jun 29 Javascript
Vue实现开关按钮拖拽效果
Sep 22 Javascript
vue3.0搭配.net core实现文件上传组件
Oct 29 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原生模板引擎 最简单的模板引擎
2012/04/25 PHP
BAT及各大互联网公司2014前端笔试面试题--JavaScript篇
2014/10/29 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
2014/11/23 Javascript
JS上传图片前实现图片预览效果的方法
2015/03/02 Javascript
jquery实现的Accordion折叠面板效果代码
2015/09/02 Javascript
jQuery多级手风琴菜单实例讲解
2015/10/22 Javascript
利用JavaScript阻止表单提交的两种方法
2016/08/11 Javascript
js CSS3实现卡牌旋转切换效果
2017/07/04 Javascript
详解webpack进阶之插件篇
2017/07/06 Javascript
ES6新增的math,Number方法
2017/08/06 Javascript
ES6扩展运算符的用途实例详解
2017/08/20 Javascript
vue init失败简单解决方法(终极版)
2017/12/22 Javascript
在vue2.0中引用element-ui组件库的方法
2018/06/21 Javascript
配置node服务器并且链接微信公众号接口配置步骤详解
2019/06/21 Javascript
5个你不知道的JavaScript字符串处理库(小结)
2020/06/01 Javascript
node.js +mongdb实现登录功能
2020/06/18 Javascript
python实现自动登录人人网并访问最近来访者实例
2014/09/26 Python
Python自动扫雷实现方法
2015/07/25 Python
Python机器学习算法库scikit-learn学习之决策树实现方法详解
2019/07/04 Python
pygame实现俄罗斯方块游戏(基础篇1)
2019/10/29 Python
Python 生成一个从0到n个数字的列表4种方法小结
2019/11/28 Python
python安装dlib库报错问题及解决方法
2020/03/16 Python
python3 sleep 延时秒 毫秒实例
2020/05/04 Python
python3实现简单飞机大战
2020/11/29 Python
解决pip安装tensorflow中出现的no module named tensorflow.python 问题方法
2021/02/20 Python
HTML5 Canvas鼠标与键盘事件demo示例
2013/07/04 HTML / CSS
美国男士西装打折店:Jos. A. Bank
2017/11/13 全球购物
悬挂训练绳:TRX
2017/12/14 全球购物
英国领先的高街书籍专家:Waterstones
2018/02/01 全球购物
英国可持续奢侈品包包品牌:Elvis & Kresse
2018/08/05 全球购物
新闻记者实习自我鉴定
2013/09/19 职场文书
竞选班长演讲稿
2013/12/30 职场文书
毕业生护理专业个人求职信范文
2014/01/04 职场文书
中秋节感想
2015/08/10 职场文书
管理者们如何制定2019年的工作计划?
2019/07/01 职场文书
解决vue-router的beforeRouteUpdate不能触发
2022/04/14 Vue.js