深拷貝:完整的把數(shù)據(jù)的任意層級屬性和值拷貝到新數(shù)據(jù)上,拷貝前后的兩個數(shù)據(jù)完全一樣,但是是不同的地址,相互不會影響。
1.
/** 返回克隆后的對象 */
MixinClone(obj) {
return JSON.parse(JSON.stringify(obj))
},
2.
let arr = {
name: 'zhangsan',
age: 18,
family: {
mather: 'mary',
father: 'tom',
brother: 'ah'
}
}
// 判斷是否是對象或者數(shù)組(返回的是布爾值)
function isObject(data) {
return Object.prototype.toString.call(data) === '[object Array]' || Object.prototype.toString.call(data) === '[object Object]'
}
function objectDeepClone(data) {
// 1.判斷data 是否是數(shù)組/對象
if (!this.isObject(data)) {
return data
}
// 2. 遞歸
const obj = Array.isArray(data)? [] : {}
for (const x in data) {
if (this.isObject(data[x])) {
obj[x] = objectDeepClone(data[x])
} else {
obj[x] = data[x]
}
}
return obj
}
objectDeepClone(arr)
console.log(objectDeepClone(arr), 'console數(shù)據(jù)============')

image.png
3.優(yōu)化后(堆棧溢出,原因便是會一直執(zhí)行遞歸,我們克隆的時候需要考慮該對象是否已被克隆,如果克隆過便記錄下來。)
/**
* 判斷是不是數(shù)組和對象
* @param {*} data 要判斷的數(shù)據(jù)
* @returns true 是 | false 否
*/
MixinIsObject(data) {
return Object.prototype.toString.call(data) === '[object Array]' || Object.prototype.toString.call(data) === '[object Object]'
},
/**
* 深拷貝函數(shù)
* @param {*} data 待拷貝的數(shù)據(jù)
* @param {*} hash 利用Map數(shù)據(jù)結(jié)構(gòu)來解決循環(huán)引用造成死循環(huán)的問題
* @returns 深拷貝后的數(shù)據(jù)
*/
MixinDeepClone(data, hash = new Map()) {
// 1. 判斷類型,只適用于array和object
if (!this.MixinIsObject(data)) {
return data
}
// 2. 如果已經(jīng)被克隆過了, 就直接return
// map.has(key) —— 如果 key 存在則返回 true,否則返回 false
if (hash.has(data)) {
return hash.get(data)
}
const obj = Array.isArray(data) ? [] : {}
// 3. 如果不存在, 將data存入到map中進(jìn)行克隆
// 鍵值對的存儲, 是因為步驟2要判斷key
hash.set(data, obj)
for (const k in data) {
if (this.MixinIsObject(data[k])) {
obj[k] = this.MixinDeepClone(data[k], hash)
} else {
obj[k] = data[k]
}
}
return obj
}