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


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 相关文章推荐
JSON JQUERY模板实现说明
Jul 03 Javascript
IE6下js通过css隐藏select的一个bug
Aug 16 Javascript
读jQuery之十二 删除事件核心方法
Jul 31 Javascript
Chrome扩展页面动态绑定JS事件提示错误
Feb 11 Javascript
jQuery层级选择器用法分析
Feb 10 Javascript
JavaScript的jQuery库中ready方法的学习教程
Aug 14 Javascript
BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)
Aug 17 Javascript
vue2.5.2使用http请求获取静态json数据的实例代码
Feb 27 Javascript
从零开始用electron手撸一个截屏工具的示例代码
Oct 10 Javascript
Vue列表循环从指定下标开始的多种解决方案
Apr 08 Javascript
解决vue net :ERR_CONNECTION_REFUSED报错问题
Aug 13 Javascript
vue el-table实现递归嵌套的示例代码
Aug 14 Vue.js
聊聊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
smarty 原来也不过如此~~呵呵
2006/11/25 PHP
PHP 网络开发详解之远程文件包含漏洞
2010/04/25 PHP
通过table标签,PHP输出EXCEL的实现方法
2013/07/24 PHP
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
PHP经典设计模式之依赖注入定义与用法详解
2019/05/21 PHP
node.js中的http.response.write方法使用说明
2014/12/14 Javascript
Jquery动态添加输入框的方法
2015/05/29 Javascript
javascript 闭包详解
2015/07/02 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
JS填写银行卡号每隔4位数字加一个空格
2016/12/19 Javascript
angular实现图片懒加载实例代码
2017/06/08 Javascript
详解关于react-redux中的connect用法介绍及原理解析
2017/09/11 Javascript
详解vue-cli脚手架中webpack配置方法
2018/08/22 Javascript
使用localStorage替代cookie做本地存储
2019/09/25 Javascript
Vue 实现复制功能,不需要任何结构内容直接复制方式
2019/11/09 Javascript
vue离开当前页面触发的函数代码
2020/09/01 Javascript
详解Python中的元组与逻辑运算符
2015/10/13 Python
Python程序中用csv模块来操作csv文件的基本使用教程
2016/03/03 Python
浅析Python中else语句块的使用技巧
2016/06/16 Python
python3.x上post发送json数据
2018/03/04 Python
python opencv 读取本地视频文件 修改ffmpeg的方法
2019/01/26 Python
Python 给屏幕打印信息加上颜色的实现方法
2019/04/24 Python
django项目中使用手机号登录的实例代码
2019/08/15 Python
python+selenium+PhantomJS抓取网页动态加载内容
2020/02/25 Python
Tensorflow中批量读取数据的案列分析及TFRecord文件的打包与读取
2020/06/30 Python
一文读懂Python 枚举
2020/08/25 Python
详解FireFox下Canvas使用图像合成绘制SVG的Bug
2019/07/10 HTML / CSS
什么是虚拟内存?虚拟内存有什么优势?
2016/02/09 面试题
高三自我鉴定
2013/10/23 职场文书
测绘工程专业个人自我评价
2013/12/01 职场文书
大学生毕业自我鉴定范文
2014/02/03 职场文书
清正廉洁演讲稿
2014/05/22 职场文书
学校法制宣传月活动总结
2014/07/03 职场文书
致800米运动员广播稿(10篇)
2014/10/17 职场文书
硕士论文致谢范文
2015/05/14 职场文书
浅谈Java父子类加载顺序
2021/08/04 Java/Android