基础类型与引用类型
五大基础类型
Underfied
Null
Boolean
Number
String
他们是固定大小的数据,存在栈中,按值传递。
let a = 1let b = a // �b拷贝aconsole.log(b) // 1a = 2 // a值变了console.log(b) // 1,b值没有变
对基本类型来说,拷贝就是复制一份同样的值给对方,双方不会被影响。
而引用类型存的是对象的引用地址,对象的大小不确定,存在堆中,普通的赋值拷贝只会复制一遍引用地址,实质上两者还是指向同一个对象。
let a = {x : 1}let b = a // �b拷贝aconsole.log(b) // {x : 1}a = {x : 2} // a值变了console.log(b) // {x : 2},b也变了
浅拷贝与深拷贝
上面的例子是普通的赋值拷贝,证明了对引用类型来说赋值拷贝是无效的,所以我们又想到了遍历一遍对象里的值,那不就搞定了吗?这就是我们说的浅拷贝啦。确实,对一个只有一层属性且属性均为基本属性的对象来说,遍历了一遍之后会拷贝成功,互不影响。但是一旦存在有属性又是引用类型的话,还是会出现一样的问题。
所以深拷贝的直观理解就是,对引用类型中每个属性进行遍历拷贝,直到遇到基本类型为止。
深浅拷贝的方案
浅拷贝方案
Object.assign() (兼容性不好)
Underscore —— _.clone()
lodash —— _.clone()
数组中concat和slice方法
深拷贝方案
JSON.parse(JSON.stringify(obj))
简单粗暴又有点dirty,但是能满足日常需求,只能处理json能理解的数据格式,当然不包括函数了,性能也没有特别好lodash —— _.cloneDeep()
很好地兼容了ES6的新引用类型,而且处理了环型对象的情况jQuery —— $.clone() / $.extend()
源码适合初学者学习,比较好理解
假如说到要来一个万能的完美的深拷贝方案,哦?不存在的。深拷贝本来就没有一个明确的定义,如何处理DOM节点的拷贝,如何拷贝原型的属性,RegExp 怎么处理,函数怎么处理。。。在知乎上有人这样问
参考文章
结语
最近比较忙,其实最好还是和大家一起讨论一下以上提及到的第三方库优秀的深拷贝源码。。所以大家可以自行去学习~~
小礼物走一
作者:Eason_Wong
链接:https://www.jianshu.com/p/48b36a788ed0