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


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 相关文章推荐
Function.prototype.call.apply结合用法分析示例
Jul 03 Javascript
jQuery判断checkbox选中状态
May 12 Javascript
JavaScript基础语法之js表达式
Jun 07 Javascript
BootStrap Table 分页后重新搜索问题的解决办法
Aug 08 Javascript
详解Vue.js——60分钟组件快速入门(上篇)
Dec 05 Javascript
JavaScript正则表达式替换字符串中图片地址(img src)的方法
Jan 13 Javascript
Vue结合原生js实现自定义组件自动生成示例
Jan 21 Javascript
canvas实现弧形可拖动进度条效果
May 11 Javascript
打通前后端构建一个Vue+Express的开发环境
Jul 17 Javascript
微信小程序实现签到功能
Oct 31 Javascript
vue+element 模态框表格形式的可编辑表单实现
Jun 07 Javascript
详解vue父子组件状态同步的最佳方式
Sep 10 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生成缩略图的类代码
2008/10/02 PHP
PHP调用C#开发的dll类库方法
2014/07/28 PHP
关于WordPress的SEO优化相关的一些PHP页面脚本技巧
2015/12/10 PHP
php常用数组函数实例小结
2016/12/29 PHP
js 实现无缝滚动 兼容IE和FF
2009/07/15 Javascript
屏蔽Flash右键信息的js代码
2010/01/17 Javascript
javascript 闭包疑问
2010/12/30 Javascript
使用jquery实现图文切换效果另加特效
2013/01/20 Javascript
JSON+HTML实现国家省市联动选择效果
2014/05/18 Javascript
JS实现点击上移下移LI行数据的方法
2015/08/05 Javascript
JavaScript中利用各种循环进行遍历的方式总结
2015/11/10 Javascript
JavaScript实现点击按钮就复制当前网址
2015/12/14 Javascript
Bootstrap网格系统详解
2016/04/26 Javascript
jQuery实现鼠标选中文字后弹出提示窗口效果【附demo源码】
2016/09/05 Javascript
Vue实现双向绑定的方法
2016/12/22 Javascript
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
2017/03/21 jQuery
微信小程序实现笑脸评分功能
2018/11/03 Javascript
[02:14]2016国际邀请赛中国区预选赛Ehome晋级之路
2016/07/01 DOTA
Flask入门教程实例:搭建一个静态博客
2015/03/27 Python
使用Python的Tornado框架实现一个简单的WebQQ机器人
2015/04/24 Python
Python元组及文件核心对象类型详解
2018/02/11 Python
centos7之Python3.74安装教程
2019/08/15 Python
面向对象学习之pygame坦克大战
2019/09/11 Python
Python函数中的可变长参数详解
2019/09/12 Python
python无序链表删除重复项的方法
2020/01/17 Python
TensorFLow 不同大小图片的TFrecords存取实例
2020/01/20 Python
Pytorch环境搭建与基本语法
2020/06/03 Python
aec加密 php_php aes加密解密类(兼容php5、php7)
2021/03/14 PHP
css3 旋转按钮 使用CSS3创建一个旋转可变色按钮
2012/12/31 HTML / CSS
Nike瑞士官网:Nike CH
2021/01/18 全球购物
迎接领导欢迎词
2014/01/11 职场文书
七年级政治教学反思
2014/02/03 职场文书
大家检讨书5000字
2014/02/03 职场文书
2016大学自主招生推荐信范文
2015/03/23 职场文书
护士自我推荐信范文
2015/03/24 职场文书
课程设计感想范文
2015/08/11 职场文书