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


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实现悬浮移动窗口(悬浮广告)的特效
Mar 12 Javascript
使用jquery解析XML示例代码
Sep 05 Javascript
javascript+ajax实现产品页面加载信息
Jul 09 Javascript
理解javascript正则表达式
Mar 08 Javascript
学习使用bootstrap3栅格系统
Apr 12 Javascript
基于jquery插件编写countdown计时器
Jun 12 Javascript
利用vue写todolist单页应用
Dec 15 Javascript
BootStrop前端框架入门教程详解
Dec 25 Javascript
使用jQuery的ajax方法向服务器发出get和post请求的方法
Jan 13 Javascript
AngularJS动态菜单操作指令
Apr 25 Javascript
javascript使用正则实现去掉字符串前面的所有0
Jul 23 Javascript
微信小程序 调用远程接口 给全局数组赋值代码实例
Aug 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版
2006/10/09 PHP
一个php导出oracle库的php代码
2009/04/20 PHP
php中删除字符串中最先出现某个字符的实现代码
2013/02/03 PHP
PHP防范SQL注入的具体方法详解(测试通过)
2014/05/09 PHP
利用javascript打开模态对话框(示例代码)
2014/01/11 Javascript
jQuery操作表格(table)的常用方法、技巧汇总
2014/04/12 Javascript
javascript初学者常用技巧
2014/09/02 Javascript
js判断checkbox是否选中个数的方法(超简单)
2016/08/19 Javascript
Jquery鼠标放上去显示全名的实现方法
2017/02/06 Javascript
vue基于viewer实现的图片查看器功能
2019/04/12 Javascript
JS解惑之Object中的key是有序的么
2019/05/06 Javascript
vue-cli+axios实现文件上传下载功能(下载接收后台返回文件流)
2019/05/10 Javascript
mpvue微信小程序开发之实现一个弹幕评论
2019/11/24 Javascript
WebStorm中如何将自己的代码上传到github示例详解
2020/10/28 Javascript
[01:30]DOTA2上海特锦赛现场采访 Loda倾情献唱
2016/03/25 DOTA
Python比较文件夹比另一同名文件夹多出的文件并复制出来的方法
2015/03/05 Python
Python登录并获取CSDN博客所有文章列表代码实例
2017/12/28 Python
python操作excel的方法(xlsxwriter包的使用)
2018/06/11 Python
Django如何自定义分页
2018/09/25 Python
详解python分布式进程
2018/10/08 Python
Python中将两个或多个list合成一个list的方法小结
2019/05/12 Python
Python读取stdin方法实例
2019/05/24 Python
python爬虫豆瓣网的模拟登录实现
2019/08/21 Python
Transpose 数组行列转置的限制方式
2020/02/11 Python
Python pytesseract验证码识别库用法解析
2020/06/29 Python
计算机学生的自我评价分享
2014/02/18 职场文书
老人祝寿主持词
2014/03/28 职场文书
民事授权委托书范文
2014/08/02 职场文书
医生党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
自愿离婚协议书范文2014
2014/10/12 职场文书
交通事故协议书范文
2014/10/23 职场文书
中小学生学籍证明
2014/10/25 职场文书
学生检讨书
2015/01/27 职场文书
2015年食品安全工作总结
2015/05/15 职场文书
运动会运动员赞词
2015/07/22 职场文书
Jupyter notebook 输出部分显示不全的解决方案
2021/04/24 Python