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


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 相关文章推荐
javascript编程起步(第三课)
Feb 27 Javascript
javascript Window及document对象详细整理
Jan 12 Javascript
jQuery find和children方法使用
Jan 31 Javascript
深入理解JavaScript系列(12) 变量对象(Variable Object)
Jan 16 Javascript
jquery eval解析JSON中的注意点介绍
Aug 23 Javascript
Javascript中Event属性搜集整理
Sep 17 Javascript
ExtJS判断IE浏览器类型的方法
Feb 10 Javascript
javascript中substring()、substr()、slice()的区别
Aug 30 Javascript
基于VuePress 轻量级静态网站生成器的实现方法
Apr 17 Javascript
node中的cookie的具体使用
Sep 13 Javascript
深入了解JavaScript 防抖和节流
Sep 12 Javascript
vue $router和$route的区别详解
Dec 02 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
通过5个php实例细致说明传值与传引用的区别
2012/08/08 PHP
浅谈PHP5.6 与 PHP7.0 区别
2019/10/09 PHP
动态载入/删除/更新外部 JavaScript/Css 文件的代码
2010/07/03 Javascript
javascript中节点的最近的相关节点访问方法
2013/03/20 Javascript
判断是否安装flash player及当前版本的JS代码
2013/08/08 Javascript
extjs render 用法介绍
2013/09/11 Javascript
javascript删除数组元素并且数组长度减小的简单实例
2014/02/14 Javascript
js返回前一页刷新本页重载页面
2014/07/29 Javascript
JavaScript动态加载样式表的方法
2015/03/21 Javascript
使用HTML+CSS+JS制作简单的网页菜单界面
2015/07/27 Javascript
js实现仿百度风云榜可重复多次调用的TAB切换选项卡效果
2015/08/31 Javascript
js使用cookie记录用户名的方法
2015/11/26 Javascript
vue-hook-form使用详解
2017/04/07 Javascript
javascript数据结构中栈的应用之符号平衡问题
2017/04/11 Javascript
详解node中创建服务进程
2017/05/09 Javascript
nodejs批量下载图片的实现方法
2017/05/19 NodeJs
Node实战之不同环境下配置文件使用教程
2018/01/02 Javascript
JS设计模式之策略模式概念与用法分析
2018/02/05 Javascript
浅谈Vue响应式(数组变异方法)
2018/05/07 Javascript
vue实现编辑器键盘抬起时内容跟随光标距顶位置向上滚动效果
2020/05/28 Javascript
详解python的数字类型变量与其方法
2016/11/20 Python
python基本语法练习实例
2017/09/19 Python
python实现RabbitMQ的消息队列的示例代码
2018/11/08 Python
python基于FTP实现文件传输相关功能代码实例
2019/09/28 Python
Python3 利用face_recognition实现人脸识别的方法
2020/03/13 Python
CSS3使用transition属性实现过渡效果
2018/04/18 HTML / CSS
详解android与HTML混合开发总结
2018/06/06 HTML / CSS
英国创新设计文具、卡片和礼品包装网站:Paperchase
2018/07/14 全球购物
大学生求职简历的自我评价
2013/10/21 职场文书
毕业生自荐书模版
2014/01/04 职场文书
女子职高个人自荐书
2014/02/01 职场文书
初三学习计划书范文
2014/04/30 职场文书
幼儿园安全工作总结2015
2015/04/20 职场文书
格列夫游记读书笔记
2015/07/01 职场文书
vue项目如何打包之项目打包优化(让打包的js文件变小)
2022/04/30 Vue.js
Vscode中SSH插件如何远程连接Linux
2022/05/02 Servers