博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js deep clone 深克隆
阅读量:6304 次
发布时间:2019-06-22

本文共 2087 字,大约阅读时间需要 6 分钟。

首先,值的拷贝,通常有三种方式,由于基本类型与引用类型在内存中存储位置和存储方式的不同,导致了以下三种概念的衍生:

  • = 赋值:多个指针指向的是同一个堆中的地址,所以相互有影响;
  • 浅拷贝:在堆中重新创建内存,拷贝前后基本数据类型不受影响,但只拷贝一层,无法拷贝子对象;所以改变浅拷贝得到的对象中的引用类型时,原始数据会受到影响;例如数组的concat和slice方法;
  • 深拷贝:对子对象也可以拷贝,拷贝前后两个对象互不影响,是对对象以及对象的所有子对象进行拷贝;思路就是递归调用浅拷贝的逻辑,把所有属于对象的属性类型都遍历赋给另一个对象即可。完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个。

看下数组结构的拷贝:

var new_arr = JSON.parse( JSON.stringify(arr) );复制代码

但此法无法拷贝函数。concat、slice、JSON.stringify 都算是技巧类,可以根据实际情况适当使用。

初步实现一个浅拷贝:

在看开源项目的过程中,经常会看到类似如下的源码。for...in循环对象的所有枚举属性,然后再使用hasOwnProperty()方法来忽略继承属性。

const shallowClone = (obj) => {      if (typeof obj !== 'object') return    let newObj = obj instanceof Array ? [] : {}      for (let key in obj) {            if (obj.hasOwnProperty(key)) {                  newObj[key] = obj[key]            }       }     return newObj}复制代码

初步实现一个深拷贝:

const deepClone = (obj) => {      if (typeof obj !== 'object') return    let newObj = obj instanceof Array ? [] : {}      for (let key in obj) {           if (typeof obj[key] === 'object') {               newObj[key] = deepClone(obj[key])           } else {                newObj[key] = obj[key]           }       }     return newObj}复制代码

深拷贝会完全的克隆一个新对象,但因为使用递归,性能会不如浅拷贝,在开发中,还是要根据实际情况进行选择。

第三方库的实现

Underscore _.clone()

实际上是一种浅复制 (shallow-copy),所有嵌套的对象和数组都是直接复制引用而并没有进行深复制。源码:

// Create a (shallow-cloned) duplicate of an object._.clone = function(obj) {  if (!_.isObject(obj)) return obj;  return _.isArray(obj) ? obj.slice() : _.extend({}, obj);};复制代码

jQuery $.extend()

var x = {    a: 1,    b: { f: { g: 1 } },    c: [ 1, 2, 3 ]};var y = $.extend({}, x),          //shallow copy    z = $.extend(true, {}, x);    //deep copyy.b.f === x.b.f       // truez.b.f === x.b.f       // false复制代码

lodash  _.clone() / _.cloneDeep()

在lodash中关于复制的方法有两个,分别是_.clone()_.cloneDeep()。其中_.clone(obj, true)等价于_.cloneDeep(obj)

jQuery 无法正确深复制 JSON 对象以外的对象,而 lodash 花了大量的代码来实现 ES6 引入的大量新的标准对象。lodash 针对存在环的对象的处理也是非常出色的。因此相较而言,lodash 在深复制上的行为反馈比前两个库好很多。

参考源:

https://juejin.im/post/59ac1c4ef265da248e75892b

https://segmentfault.com/a/1190000002801042

https://github.com/mqyqingfeng/Blog/issues/32

转载地址:http://xebxa.baihongyu.com/

你可能感兴趣的文章
Python编程语言
查看>>
十四、转到 linux
查看>>
Got error 241 'Invalid schema
查看>>
ReferenceError: event is not defined
查看>>
男人要内在美,更要外在美
查看>>
为什么要跟别人比?
查看>>
app启动白屏
查看>>
Oracle 提高查询性能(基础)
查看>>
学习知识应该像织网一样去学习——“网状学习法”
查看>>
Hadoop集群完全分布式安装
查看>>
QString,char,string之间赋值
查看>>
我的友情链接
查看>>
Nginx+mysql+php-fpm负载均衡配置实例
查看>>
shell脚本操作mysql数据库 (部份参考)
查看>>
MySql之基于ssl安全连接的主从复制
查看>>
informix的逻辑日志和物理日志分析
查看>>
VMware.Workstation Linux与windows实现文件夹共享
查看>>
ARM inlinehook小结
查看>>
wordpress admin https + nginx反向代理配置
查看>>
管理/var/spool/clientmqueue/下的大文件
查看>>