JavaScript 深层克隆对象详解及实例


Posted in Javascript onNovember 03, 2016

 JavaScript 深层克隆对象

今天做项目,有个需求需要用到深层克隆对象,并且要求在原型链上编程 于是心血来潮索性来复习一下这个知识点,在网上找了相应的知识,

克隆对象,这名词看着高大上,其实也没什么,便是拷贝一个长的一模一样的对象
也许有初学的小伙伴在想,那还不简单么,so easy

var obj1 = {name: 'payen'};

var obj2 = obj1;

这可并不是克隆对象,obj1和obj2根本就是同一个对象,

他俩指向同一个内存地址空间,拿到了同样的一个小房子

这是应为对象是引用值

说到引用值

JavaScript中引用值只有对象

这里注意,数组是特殊的对象,函数也是特殊的可执行对象, 也就是说,它们也是对象 ,所谓深层克隆对象就是说它并不想要同样的房子,房子你也要给我复制一份一模一样的 不知道我这么说大家能不能理解= ̄ω ̄= ,也就是深层克隆对象引用值要拷贝,而相对的浅层克隆对象只要把那个引用值拿过来就好了 ,不明白不要紧,看完代码就理解了

首先来一起看看浅层克隆对象吧

var house = {
  name: 'payen',
  people: {
    father: true,
    mother: true
  }
}
function easyClone(obj){
  var newObj = {};
  for(var prop in obj){
    if(obj.hasOwnProperty(prop)){
      newObj[prop] = obj[prop];
    }
  }
  return newObj;
}
var newHouse = easyClone(house);

不要吐槽我用easy,一时想不起来“浅”英文咋说来着(真不知道我英语六级怎么过的) 。关于那个for-in有一个小性能问题,感兴趣的童鞋可以看看我的另一篇文章

这段代码很简单我就不多解释了

来看看chrome控制台

JavaScript 深层克隆对象详解及实例

看样子很棒的样子

那么我现在做一件事

给新房子加一个人

JavaScript 深层克隆对象详解及实例

看来这个”新房子”并不新啊,不要被变量名字迷惑了所以,有引用值出现,浅层克隆并不好用了

既然如此,我们怎么办呢

既然要得到新的对象,我们创建一个新对象,把旧对象内部的东西,再拷贝到新对象不就得了

还有一个问题如果对象里还有对象呢

那么就继续重复创建添加的过程,很显然是一个循环的过程

不过循环有两种

迭代

递归

毫无疑问递归更胜一筹

在递归循环中,遇到满足终止条件的条件时逐层返回来结束 ,那么我们就可以通过递归逐层查找引用值,直到没有引用值为止
还是看代码吧

var house = {
  name: 'payen',
  people: {
    father: true,
    mother: true,
    child: {
      age: 1
    }
  },
  money: [1000,2000,3000]
}
function deepClone(original, target){
  var target = target || {};// 如果target为undefined或没传参,设置空对象
  for(var prop in original){// 遍历原对象
    if(original.hasOwnProperty(prop)){// 只拷贝对象内部,不考虑原型链
      if(typeof original[prop] === 'object'){// 引用值
        if(Object.prototype.toString.call(original[prop]) === '[object Array]'){
          target[prop] = [];// 处理数组引用值
        }else{
          target[prop] = {};// 处理对象引用值
        }// 可以用三目运算符
        deepClone(original[prop],target[prop]);// 递归克隆
      }else{// 基本值
        target[prop] = original[prop];
      }  
    }
  }
  return target;
}
var newHouse = deepClone(house);

上面写了那个if-else挺适合用三目运算符的,不过我感觉太冗长了,强迫症表示看了很不舒服 ,为了证明它真的深层克隆了,我特意把原始房子变复杂了 ,(我们不考虑函数的深层克隆,麻烦并且意义不大) ,这回它真的是新房子了

JavaScript 深层克隆对象详解及实例

我就不展开了

可以看出来在新对象的引用值改动,旧对象并没有变

在原型链上编程同理

var house = {
  name: 'payen',
  people: {
    father: true,
    mother: true,
    child: {
      age: 1
    }
  },
  money: [1000,2000,3000]
}
Object.prototype.cloneTo = function(obj){
  var obj = obj || {};
  for(var prop in this){
    if(this.hasOwnProperty(prop)){
      if(typeof this[prop] === 'object'){
        if(Object.prototype.toString.call(this[prop]) === '[object Array]'){
          obj[prop] = [];
        }else{
          obj[prop] = {};
        }
        this[prop].cloneTo(obj[prop]);
      }else{
        obj[prop] = this[prop];
      }
    }
  }
  return obj;
}
var newHouse = {};
house.cloneTo(newHouse);

感谢阅读,希望能帮到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
一个tab标签切换效果代码
Mar 27 Javascript
利用js判断浏览器类型(是否为IE,Firefox,Opera浏览器)
Nov 22 Javascript
JS网页在线获取鼠标坐标值的方法
Feb 28 Javascript
JavaScript结合Bootstrap仿微信后台多图文界面管理
Jul 22 Javascript
Angular2平滑升级到Angular4的步骤详解
Mar 29 Javascript
认识less和webstrom的less配置方法
Aug 02 Javascript
微信小程序使用wxParse解析html的方法示例
Jan 17 Javascript
Webpack4 使用Babel处理ES6语法的方法示例
Mar 07 Javascript
jquery实现动态创建form并提交的方法示例
May 27 jQuery
Vue+webpack实现懒加载过程解析
Feb 17 Javascript
JS禁用右键、禁用Ctrl+u、禁用Ctrl+s、禁用F12的实现代码
Dec 01 Javascript
vue+vant实现购物车全选和反选功能
Nov 17 Vue.js
jQuery.ajax实现根据不同的Content-Type做出不同的响应
Nov 03 #Javascript
简单学习vue指令directive
Nov 03 #Javascript
Vue.js常用指令汇总(v-if、v-for等)
Nov 03 #Javascript
巧用Vue.js+Vuex制作专门收藏微信公众号的app
Nov 03 #Javascript
原生javascript实现的ajax异步封装功能示例
Nov 03 #Javascript
探索Vue.js component内容实现
Nov 03 #Javascript
javascript跨域请求包装函数与用法示例
Nov 03 #Javascript
You might like
利用PHP实现与ASP Banner组件相似的类
2006/10/09 PHP
PHP mail 通过Windows的SMTP发送邮件失败的解决方案
2009/05/27 PHP
smarty中js的调用方法示例
2014/10/27 PHP
php实现简易聊天室应用代码
2015/09/23 PHP
js获取变量
2006/08/24 Javascript
使用jquery与图片美化checkbox和radio控件的代码(打包下载)
2010/11/11 Javascript
jQuery获得document和window对象宽度和高度的方法
2015/03/25 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
2015/12/23 Javascript
jQuery获取及设置表单input各种类型值的方法小结
2016/05/24 Javascript
老生常谈JavaScript数组的用法
2016/06/10 Javascript
AngularJS Bootstrap详细介绍及实例代码
2016/07/28 Javascript
js替换字符串中所有指定的字符(实现代码)
2016/08/17 Javascript
JavaScript的事件机制详解
2017/01/17 Javascript
深入理解javascript的getTime()方法
2017/02/16 Javascript
微信小程序 request接口的封装实例代码
2017/04/26 Javascript
浅谈在fetch方法中添加header后遇到的预检请求问题
2017/08/31 Javascript
深入理解Angular4订阅(Subscribe)与取消
2017/11/22 Javascript
在layui下对元素进行事件绑定的实例
2019/09/06 Javascript
如何在vue-cli中使用css-loader实现css module
2021/01/07 Vue.js
[10:05]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD 选手采访
2021/03/11 DOTA
Python两个内置函数 locals 和globals(学习笔记)
2016/08/28 Python
关于Python正则表达式 findall函数问题详解
2018/03/22 Python
PyQt5每天必学之滑块控件QSlider
2018/04/20 Python
pandas多级分组实现排序的方法
2018/04/20 Python
使用python批量读取word文档并整理关键信息到excel表格的实例
2018/11/07 Python
详解Python计算机视觉 图像扭曲(仿射扭曲)
2019/03/27 Python
python接口自动化测试之接口数据依赖的实现方法
2019/04/26 Python
pandas 使用均值填充缺失值列的小技巧分享
2019/07/04 Python
pytorch中使用cuda扩展的实现示例
2020/02/12 Python
pycharm 更改创建文件默认路径的操作
2020/02/15 Python
解决Tensorflow2.0 tf.keras.Model.load_weights() 报错处理问题
2020/06/12 Python
经济信息系毕业生自荐信范文
2014/03/15 职场文书
社区护士演讲稿
2014/08/27 职场文书
单位实习工作证明怎么写
2014/11/02 职场文书
学术研讨会主持词
2015/07/04 职场文书
写一个Python脚本下载哔哩哔哩舞蹈区的所有视频
2021/05/31 Python