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


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获取URL中参数解决中文乱码问题的两种方法
Dec 18 Javascript
get(0).tagName获得作用标签示例代码
Oct 08 Javascript
jQuery实现网页抖动的菜单抖动效果
Aug 07 Javascript
JavaScript制作淘宝星级评分效果的思路
Jun 23 Javascript
Vue.js每天必学之方法与事件处理器
Sep 06 Javascript
JavaScript实现审核流程状态的动态显示进度条
Mar 15 Javascript
通过js修改input、select默认字体颜色
Apr 19 Javascript
使用requirejs模块化开发多页面一个入口js的使用方式
Jun 14 Javascript
jQuery 实现鼠标画框并对框内数据选中的实例代码
Aug 29 jQuery
微信小程序使用gitee进行版本管理
Sep 20 Javascript
vue中的inject学习教程
Apr 24 Javascript
关于javascript中的promise的用法和注意事项(推荐)
Jan 15 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在XP下IIS和Apache2服务器上的安装
2006/09/05 PHP
source.php查看源文件
2006/12/09 PHP
PHP通过微信跳转的Code参数获取用户的openid(关键代码)
2016/07/06 PHP
PHP经典实用正则表达式小结
2017/05/04 PHP
PHP实现微信退款功能
2018/10/02 PHP
Yii2.0建立公共方法简单示例
2019/01/29 PHP
Js中sort()方法的用法
2006/11/04 Javascript
Js 获取HTML DOM节点元素的方法小结
2009/04/24 Javascript
js对象的构造和继承实现代码
2010/12/05 Javascript
jQuery实现简单的tab标签页效果
2016/09/12 Javascript
bootstarp modal框居中显示的实现代码
2017/02/18 Javascript
Vue动态组件实例解析
2017/08/20 Javascript
在vue项目中使用element-ui的Upload上传组件的示例
2018/02/08 Javascript
vue+element-ui动态生成多级表头的方法
2018/08/28 Javascript
json数据格式常见操作示例
2019/06/13 Javascript
通过GASP让vue实现动态效果实例代码详解
2019/11/24 Javascript
[04:31]2016国际邀请赛中国区预选赛妖精采访
2016/06/27 DOTA
python统计文本字符串里单词出现频率的方法
2015/05/26 Python
详解python使用递归、尾递归、循环三种方式实现斐波那契数列
2018/01/16 Python
python numpy 部分排序 寻找最大的前几个数的方法
2018/06/27 Python
pycharm在调试python时执行其他语句的方法
2018/11/29 Python
python opencv minAreaRect 生成最小外接矩形的方法
2019/07/01 Python
python+numpy按行求一个二维数组的最大值方法
2019/07/09 Python
python实现翻转棋游戏(othello)
2019/07/29 Python
Python之Numpy的超实用基础详细教程
2019/10/23 Python
StubHub哥伦比亚:购买和出售您的门票
2016/10/20 全球购物
澳大利亚窗帘商店:Curtain Wonderland
2019/12/01 全球购物
制药工程专业应届生求职信
2013/09/24 职场文书
竞选大队委员演讲稿
2014/04/28 职场文书
办公室文员岗位职责范本
2014/06/12 职场文书
学校领导班子对照检查材料
2014/09/24 职场文书
2014年党员个人工作总结
2014/12/02 职场文书
离婚协议书怎么写的
2014/12/14 职场文书
先进事迹材料范文
2014/12/29 职场文书
乡镇党建工作总结2015
2015/05/19 职场文书
CSS实现单选折叠菜单功能
2021/11/01 HTML / CSS