数据类型
在理解深浅拷贝之前需要先从js的数据类型说起,简单来说分为两种,
- 基础数据类型(String,Boolean,null,undefined,Number,symbol(es6新增,表示一个独一无二的值))
- 引用数据类型(Object (可以细分为Array,Function,Date等)) 基础数据类型按值引用,值存在栈中。引用数据类型的数据保存在堆中,变量是一个指向堆中实际数据的引用,存在栈中。
浅拷贝
浅拷贝实际是新建一份新的数据,如果拷贝的值是基础数据类型,拷贝的就是基础数据类型的值;如果拷贝的值是引用数据类型,拷贝的就是内存地址。即浅拷贝可以拷贝一层,深层次实际是和源数据共享内存地址
浅拷贝实现方法
- es6扩展运算符
let a = {a: 1}
let b = {...a}
- Object.assign()
let a = {b: 1}
let b = Object.assign({},a)
- 直接=赋值
- 遍历
// 浅拷贝
function shallow (params) {
let newObj = {}
for (const key in params) {
if (Object.hasOwnProperty.call(params, key)) {
newObj[key] = params[key]
}
}
return newObj
}
深拷贝
深拷贝是在内存中新开辟一片地址,与之前的值相同,但是引用地址不相同,可以理解为克隆人。
深拷贝的实现方式
- JSON格式化,但是这样存在的问题是源对象中值为undefined或者是function的属性并不会被拷贝到新的变量中,可能会造成数据的缺失
let a = {a:1,b:undefined,c:null,d:function(){}}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {a: 1, c: null}
- 递归拷贝
function deepClone (obj, map = new WeakMap()) {
if (type obj !== 'object' || obj === null) return obj
if (map.has(obj)) return map.get(obj)
let res = Array.isArray(obj) ? [] : {}
map.set(obj, res)
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) res[key] = deepClone(obj[key], map)
}
return res
}
- 第三方库,如lodash的deepClone,jquery的.extend等
结尾
写作的目的是为了总结一些知识点,有什么不对的地方希望大家多多指教,轻喷。