JS中的深拷贝与浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
浅拷贝
(1) 直接赋值
//同一个地址
var arr = { }
arr2 = arr
(2) Object.assign() 只是一级属性复制,比浅拷贝多拷贝一层。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
//{ a: 1, b: 4, c: 5 }
console.log(returnedTarget);
//{ a: 1, b: 4, c: 5
(3) 展开运算符...,只是一级属性复制,比浅拷贝多拷贝一层
let obj={
name:"jack",//不受影响
arr:[1,2,3] //拷贝地址,还是同一个值
}
let new={...obj}
new.arr.splice(1,1)
//obj arr:[1,3]
//new arr:[1,3]
深拷贝
(1) JSON.parse(JSON.stringify())数组对象都好用的方法
缺点: 不能有undefined和function
const obj1 = JSON.parse(JSON.stringify(obj));
//undefind与function直接丢失
(2) 递归深复制,一层层复制,性能不好,占用内存
function deepCopy(newData,oldData) {
for (let key in oldData) {
//判断属性值属于哪种数据类型 根据属性值类型的不同做不同的操作
//1.获取属性值 oldobj[Key]
let item = oldData[key]
//2.1判断这个值是否是数组
//2.2判断这个值是否是对象
//2.3否则属于简单数据类型
if (item instanceof Array) {
newData[key] = []
deepCopy(newData[key], item)
} else if (item instanceof Object) {
newData[key] = {}
deepCopy(newData[key], item)
} else {
newData[key] = item
}
}
}
const cloneDeep = data => {
const newData = Array.isArray(data) ? [] : {}
for (let key in data) {
if (data[key] && typeof data[key] === 'object') {
newData[key] = cloneDeep(data[key])
} else {
newData[key] = data[key]
}
}
return newData
}
(3)优化方案
/**
* 判断对象属性值是否有对象
* @param {} data
* @returns
*/
const isObjectValue = data => {
for (let key in data) {
if (data[key] && typeof data[key] === 'object') {
if(Object.prototype.toString.call(data[key]) !== '[object Function]'){
return true
}
}
}
}
/**
* 递归判断数据类型
* Function或undefined返回为true
*/
const isFunctionOrUndefined = data => {
for (let key in data) {
if (data[key] === undefined) {
return true
} else if (data[key] && Object.prototype.toString.call(data[key]) === '[object Function]') {
return true //Function
} else if (data[key] && typeof data[key] === 'object') {
isFunctionOrUndefined(data[key])
}
}
}
/**
* 拷贝对象 优化方案
* @param {*} obj 原对象
* @param {*} cloneObj 返回拷贝对象
*/
const cloneDeepObj = obj => {
if (obj === undefined) {
throw new TypeError('param is not undefined')
}
//判断拷贝对象只有一层及属性值都不是对象,使用Object.assign()
if (!isObjectValue(obj)) {
return { ...obj }
}
//判断类型,如果不是Function或undefined使用JSON方式
if (!isFunctionOrUndefined(obj)) {
return JSON.parse(JSON.stringify(obj))
}
return cloneDeep(obj)
}
思考:
数组中的map方法是深拷贝还是浅拷贝呢?
let arr = [1, 2, { name: "jack" }, [5, 6, 7]]
let newarr = arr.map((item) => item)
arr[2].name = 'root'
arr[0] = 0
console.log("旧数组>>>", arr);
//0: 0
//1: 2
//2: {name: 'root'}
//3: (3) [5, 6, 7]
console.log("新数组---", newarr);
//0: 1
//1: 2
//2: {name: 'root'}
//3: (3) [5, 6, 7]
//结果:只是一级属性复制,比浅拷贝多拷贝了一层