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


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 相关文章推荐
extJs 下拉框联动实现代码
Apr 09 Javascript
Js组件的一些写法
Sep 10 Javascript
jQuery实现友好的轮播图片特效
Jan 12 Javascript
json格式数据的添加,删除及排序方法
Jan 21 Javascript
jQuery ajax分页插件实例代码
Jan 27 Javascript
原生JS改变透明度实现轮播效果
Mar 24 Javascript
get  post jsonp三种数据交互形式实例详解
Aug 25 Javascript
Vue.js划分组件的方法
Oct 29 Javascript
Javascript实现运算符重载详解
Apr 07 Javascript
Vue和React组件之间的传值方式详解
Jan 31 Javascript
jQuery删除/清空指定元素的所有子节点实例代码
Jul 04 jQuery
layui实现图片虚拟路径上传,预览和删除的例子
Sep 25 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 一个随机字符串生成代码
2010/05/26 PHP
将一维或多维的数组连接成一个字符串的php代码
2010/08/08 PHP
PHP函数之error_reporting(E_ALL ^ E_NOTICE)详细说明
2011/07/01 PHP
phpmail类发送邮件函数代码
2012/02/20 PHP
php用户注册页面利用js进行表单验证具体实例
2013/10/17 PHP
php语言的7种基本的排序方法
2020/12/28 PHP
Mootools 1.2教程 选项卡效果(Tabs)
2009/09/15 Javascript
父页面显示遮罩层弹出半透明状态的dialog
2014/03/04 Javascript
js/jquery判断浏览器的方法小结
2014/09/02 Javascript
jquery实现的省市区三级联动
2015/04/02 Javascript
详解AngularJS中自定义指令的使用
2015/06/17 Javascript
JS实现的仿QQ空间图片弹出效果代码
2016/02/23 Javascript
jQuery Mobile框架中的表单组件基础使用教程
2016/05/17 Javascript
浅谈jQuery 中的事件冒泡和阻止默认行为
2016/05/28 Javascript
基于Bootstrap的Metronic框架实现条码和二维码的生成及打印处理操作
2016/08/29 Javascript
微信小程序 跳转传参数与传对象详解及实例代码
2017/03/14 Javascript
JS与jQuery实现子窗口获取父窗口元素值的方法
2017/04/17 jQuery
Angular客户端请求Rest服务跨域问题的解决方法
2017/09/19 Javascript
phantomjs导出html到pdf的方法总结
2017/10/19 Javascript
js实现小时钟效果
2020/03/25 Javascript
Element-ui 自带的两种远程搜索(模糊查询)用法讲解
2021/01/29 Javascript
[59:26]DOTA2上海特级锦标赛D组资格赛#1 EG VS VP第二局
2016/02/28 DOTA
用Python编写一个简单的俄罗斯方块游戏的教程
2015/04/03 Python
python中import reload __import__的区别详解
2017/10/16 Python
pandas.DataFrame 根据条件新建列并赋值的方法
2018/04/08 Python
python 日期操作类代码
2018/05/05 Python
在Pycharm中设置默认自动换行的方法
2019/01/16 Python
python使用for循环计算0-100的整数的和方法
2019/02/01 Python
Lookfantastic德国官网:英国知名美妆购物网站
2017/06/11 全球购物
美国大码时尚女装购物网站:ELOQUII
2017/12/28 全球购物
中国跨境电子商务网站:NewFrog
2018/03/10 全球购物
Mybag美国/加拿大:英国奢华包包和名牌手袋网站
2020/02/16 全球购物
优秀士兵先进事迹
2014/02/06 职场文书
2014年党的群众路线教育实践活动整改措施(个人版)
2014/09/25 职场文书
2014年教研室工作总结
2014/12/06 职场文书
Pytorch中的学习率衰减及其用法详解
2021/06/05 Python