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


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 EasyUI 开源插件套装 完全替代ExtJS
Mar 24 Javascript
Jquery 扩展方法
May 06 Javascript
利用JavaScript检测CPU使用率自己写的
Mar 22 Javascript
script标签属性用type还是language
Jan 21 Javascript
EasyUi datagrid 实现表格分页
Feb 10 Javascript
TypeScript 学习笔记之基本类型
Jun 19 Javascript
jquery实现清新实用的网页菜单效果
Aug 28 Javascript
angular框架实现全选与单选chekbox的自定义
Jul 06 Javascript
详解基于vue-router的动态权限控制实现方案
Sep 28 Javascript
js利用拖放实现添加删除
Aug 27 Javascript
cypress测试本地web应用
Jun 01 Javascript
JS前端可视化canvas动画原理及其推导实现
Aug 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
咖啡界又出新概念,无需咖啡豆的分子咖啡
2021/03/03 咖啡文化
php xfocus防注入资料
2008/04/27 PHP
PHP 一个页面执行时间类代码
2010/03/05 PHP
PHP实现的多彩标签效果代码分享
2014/08/21 PHP
PHP实现查询两个数组中不同元素的方法
2016/02/23 PHP
PHP中类的继承和用法实例分析
2016/05/24 PHP
PHP实现适用于文件内容操作的分页类
2016/06/15 PHP
FileUpload 控件 禁止手动输入或粘贴的实现代码
2010/04/07 Javascript
location.href 在IE6中不跳转的解决方法与推荐使用代码
2010/07/08 Javascript
到处都是jQuery选择器的年代 不了解它们的性能,行吗
2012/06/18 Javascript
jQuery的attr与prop使用介绍
2013/10/10 Javascript
JavaScript通过setTimeout实时显示当前时间的方法
2015/04/16 Javascript
jQuery EasyUI Dialog拖不下来如何解决
2015/09/28 Javascript
javascript 中的 delete及delete运算符
2015/11/15 Javascript
BootStrap Datetimepicker 汉化的实现代码
2017/02/10 Javascript
Node.js读取文件内容示例
2017/03/07 Javascript
微信小程序学习之数据处理详解
2017/07/05 Javascript
详解node服务器中打开html文件的两种方法
2017/09/18 Javascript
SeaJS中use函数用法实例分析
2017/10/10 Javascript
Element输入框带历史查询记录的实现示例
2019/01/15 Javascript
Bootstrap实现省市区三级联动(亲测可用)
2019/07/26 Javascript
解决layui数据表格table的横向滚动条显示问题
2019/09/04 Javascript
[45:56]Ti4正赛第一天 VG vs NEWBEE 3
2014/07/19 DOTA
Django自定义分页与bootstrap分页结合
2021/02/22 Python
Python内建序列通用操作6种实现方法
2020/03/26 Python
PythonPC客户端自动化实现原理(pywinauto)
2020/05/28 Python
如何在Python3中使用telnetlib模块连接网络设备
2020/09/21 Python
浅析Python模块之间的相互引用问题
2021/02/26 Python
飞利浦比利时官方网站:Philips比利时
2016/08/24 全球购物
英语自荐信常用语句
2013/12/13 职场文书
创业计划书六个要素
2013/12/26 职场文书
大学生的创业计划书就该这么写
2014/01/30 职场文书
2015年全民国防教育日活动总结
2015/03/23 职场文书
给校长的建议书作文500字
2015/09/14 职场文书
2019年入党思想汇报
2019/03/25 职场文书
css3实现的加载动画效果
2021/04/07 HTML / CSS