引入的赋值:指向同一个对象,相互之间会影响
对象的浅拷贝:只是浅层的拷贝,内部引入对象时,依然会相互影响
对象的深拷贝:两个对象不再有任何关系,不会相互影响
JSON实现深拷贝
const obj = JSON.parse(JSON.stringify(对象))
上面的方法可以实现深拷贝。但是:
1:当对象中存在function函数的时候,会自动忽略
2:Symbol也会被忽略
3:如果对象中存在对象的循环引用,则会报错
回调函数实现
function isObject(value){
const typeValue = typeof value
return (value !== null) && (typeValue === "function" || typeValue === "object")
}
function deepClone(orginValue){
if(!isObject(originValue)){
return originValue
}
const newObj = {}
for(const key in orginValue){
newObj[key] = deepClone(orginValue[key])
}
return newObj
}
多种类型判断
function isObject(value) {
const valueType = typeof value
return (value !== null) && (valueType === "object" || valueType === "function")
}
function deepClone(originValue) {
// 判断是否是一个Set类型
if (originValue instanceof Set) {
return new Set([...originValue])
}
// 判断是否是一个Map类型
if (originValue instanceof Map) {
return new Map([...originValue])
}
// 判断如果是Symbol的value, 那么创建一个新的Symbol
if (typeof originValue === "symbol") {
return Symbol(originValue.description)
}
// 判断如果是函数类型, 那么直接使用同一个函数
if (typeof originValue === "function") {
return originValue
}
// 判断传入的originValue是否是一个对象类型
if (!isObject(originValue)) {
return originValue
}
// 判断传入的对象是数组, 还是对象
const newObject = Array.isArray(originValue) ? []: {}
for (const key in originValue) {
newObject[key] = deepClone(originValue[key])
}
// 对Symbol的key进行特殊的处理
const symbolKeys = Object.getOwnPropertySymbols(originValue)
for (const sKey of symbolKeys) {
// const newSKey = Symbol(sKey.description)
newObject[sKey] = deepClone(originValue[sKey])
}
return newObject
}
// 测试代码
let s1 = Symbol("aaa")
let s2 = Symbol("bbb")
const obj = {
name: "why",
age: 18,
friend: {
name: "james",
address: {
city: "广州"
}
},
// 数组类型
hobbies: ["abc", "cba", "nba"],
// 函数类型
foo: function(m, n) {
console.log("foo function")
console.log("100代码逻辑")
return 123
},
// Symbol作为key和value
[s1]: "abc",
s2: s2,
// Set/Map
set: new Set(["aaa", "bbb", "ccc"]),
map: new Map([["aaa", "abc"], ["bbb", "cba"]])
}
const newObj = deepClone(obj)
console.log(newObj === obj)
obj.friend.name = "kobe"
obj.friend.address.city = "成都"
console.log(newObj)
console.log(newObj.s2 === obj.s2)
循环引用添加
function isObject(value){
const valueType = typeof value
return (value !== null) && (valueType === "object" || valueType === "function")
}
function deepClone(originValue,map = new WeakMap()){
//判断是否是一个Set类型
if(originValue instanceof Set){
return new Set([...originValue])
}
if(originValue instanceof Map){
return new Map([...originValue])
}
//判断当前传入的对象是否是Symbol类型
if(typeof originValue === "symbol"){
return Symbol(originValue.description)
}
//判断传入的originValue是否是一个对象类型
if(typeof originValue === "function"){
return originValue
}
//判断传入的originValue是否是一个对象类型
if(!isObject(originValue)){
return originValue
}
if(map.has(originValue)){
return map.get(originValue)
}
//判断传入的对象是数组还是对象
const newObject = Array.isArray(originValue) ? [] : {}
map.set(originValue,newObject)
for(const key in originValue){
newObject[key] = deepClone(originValue[key],map)
}
//对Symbol的key进行特殊的处理
const symbolKeys = Object.getOwnPropertySymbols(originValue)
for(const sKey of symbolKeys){
newObject[sKey] = deepClone(originValue[sKey],map)
}
return newObject
}
let s1 = Symbol("aaa")
let s2 = Symbol("bbb")
const obj = {
name:"aa",
friend:{
name:"bb",
parent:{
name:"cc",
}
},
hobby:["ABC","AAA","CCC"],
foo:function(){
console.log("1111")
},
[s1]:"abc",
s2:s2,
set: new Set(["aaa","bbb","ccc"]),
map: new Map([["111","222"],["333"]]),
}
obj.info = obj
const Nobj = deepClone(obj)
console.log(Nobj)
console.log(Nobj === obj)