浅拷贝和深拷贝的引用赋值的关系
浅拷贝
声明一个对象
const info={
name:'ava',
age:18,
address:'aaa',
friend:{
name:'blob',
age:22,
address:'bbb',
}
}
引用赋值
const obj1=info
展开语法
const obj2 = {...info}
Object.assign()
const obj3=Object.assign({},info)
浅拷贝的时,会对原始数据类型进行复制,拷贝后的原始数据类型是单独了,但是引用数据类型,只是复制的内存地址,修改数据,会影响到原有的对象的数据,为了解决这个问题,提出来深拷贝
深拷贝
JSON方法
const obj4 = JSON.parse(Json.stringify(info))
转为字符串后,解析为对象
当对象中存在函数、symbol等等属性的时,JSON无法复制,会自动跳过,且内部存在循环引用的时,也无法赋值,需要自定义深拷贝函数
自定义深拷贝函数
const info={
name:'方佳怡\n',
phone:'19594736068',
age:18,
email:'cee6@9o7ft91.cn',
address: {
province:'黑龙江省',
city:'鹤岗市',
county:'萝北县',
town:'肇兴镇'
},
friend:{
name:'黎慧嘉',
phone:'14558873098',
age:18,
email:'d904@8odmq.cn',
address: {
province:'云南省',
city:'昆明市',
county:'石林彝族自治县',
town:'大可乡'
},
}
}
一般情况
基础架构
const deepCopy=(originValue)=>{
// 需要一个完全的新对象
const newObj={}
// 对传入的对象进行遍历
for (const Key in originValue) {
//当是普通值,就直接引用赋值,当时对象,就进行递归调用赋值
newObj[Key] = originValue[Key]
}
return newObj
}
考虑到非对象传入
//判断一个标识符是否是对象
const isObject = (value) => {
//当null、object、array 都是显示为对象、function显示为函数
const valueType = typeof value
return (value!==null) && (valueType==="object"||valueType==="function")
}
const deepCopy=(originValue)=>{
// 如果是对象传入,需要一个完全的新对象,不是对象,则返回原数据
if (!isObject(originValue)){
return originValue
}
const newObj={}
// 对传入的对象进行遍历
for (const Key in originValue) {
//当是普通值,就直接引用赋值,当时对象,就进行递归调用赋值
newObj[Key] = deepCopy(originValue[Key])
}
return newObj
}
数组深拷贝
当是数组是[] 当是对象时{}
const info=[
{name:'方语晨', phone:'13150248220'},
{name:'方慧嘉', phone:'15363311534'},
{name:'熊淑华', phone:'15595869397'},
{name:'李雨泽', phone:'13942751389'},
{name:'蒋嘉乐', phone:'18837108834'}
]
//判断一个标识符是否是对象
const isObject = (value) => {
//当null、object、array 都是显示为对象、function显示为函数
const valueType = typeof value
return (value!==null) && (valueType==="object"||valueType==="function")
}
const deepCopy=(originValue)=>{
// 如果是对象传入,需要一个完全的新对象,不是对象,则返回原数据
if (!isObject(originValue)){
return originValue
}
//当是数组是[] 当是对象时{}
const newObj=Array.isArray(originValue)? [] : {}
// 对传入的对象进行遍历
for (const Key in originValue) {
//当是普通值,就直接引用赋值,当时对象,就进行递归调用赋值
newObj[Key] = deepCopy(originValue[Key])
}
return newObj
}
const newObj = deepCopy(info)
console.log(newObj)
深拷贝其他类型
Set
//当前值是set时
if (originValue instanceof Set){
const newSet = new Set()
for (const setItem of originValue) {
newSet.add(deepCopy(setItem))
}
return newSet
}
Function
函数类型不需要深拷贝
值是Symbol
//当前是symbol 需要创建一个新的symbol
if (typeof originValue==='symbol'){
return Symbol(originValue.description)
}
key是Symbol
const symbolkeys = Object.getOwnPropertyDescriptor(originValue)
for (const symbolkey in symbolkeys) {
newObj[Symbol(symbolkeys.description)]=deepCopy(originValue[symbolkey])
}
单独循环
总和
const set = new Set(["0DJ","8eC","N85","ALK","CbO","QZ7","QsL","ghC","L6v","WdR"]);
const s1 = Symbol()
const info={
name:'方佳怡',
phone:'19594736068',
age:18,
set:set,
[s1]:123,
symbolKey:Symbol(),
email:'cee6@9o7ft91.cn',
address: {
province:'黑龙江省',
city:'鹤岗市',
county:'萝北县',
town:'肇兴镇'
},
}
//判断一个标识符是否是对象
const isObject = (value) => {
//当null、object、array 都是显示为对象、function显示为函数
const valueType = typeof value
return (value!==null) && (valueType==="object"||valueType==="function")
}
const deepCopy=(originValue)=>{
//当前是symbol 需要创建一个新的symbol
if (typeof originValue==='symbol'){
return Symbol(originValue.description)
}
// 如果是对象传入,需要一个完全的新对象,不是对象,则返回原数据
if (!isObject(originValue)){
return originValue
}
//当前值是set时
if (originValue instanceof Set){
const newSet = new Set()
for (const setItem of originValue) {
newSet.add(deepCopy(setItem))
}
return newSet
}
//当是数组是[] 当是对象时{}
const newObj=Array.isArray(originValue)? [] : {}
// 对传入的对象进行遍历
for (const Key in originValue) {
//当是普通值,就直接引用赋值,当时对象,就进行递归调用赋值
newObj[Key] = deepCopy(originValue[Key])
}
const symbolkeys = Object.getOwnPropertyDescriptor(originValue)
for (const symbolkey in symbolkeys) {
newObj[Symbol(symbolkeys.description)]=deepCopy(originValue[symbolkey])
}
return newObj
}
const newObj = deepCopy(info)
console.log(newObj)
深拷贝循环引用
将每一次的拷贝的值存入map,并且每一次判断是否已经存在,有就直接返回,同时为了考虑垃圾回收,需要使用weakmap
const set = new Set(["0DJ","8eC","N85","ALK","CbO","QZ7","QsL","ghC","L6v","WdR"]);
const s1 = Symbol()
const info={
name:'方佳怡',
phone:'19594736068',
age:18,
set:set,
[s1]:123,
symbolKey:Symbol(),
email:'cee6@9o7ft91.cn',
address: {
province:'黑龙江省',
city:'鹤岗市',
county:'萝北县',
town:'肇兴镇'
},
}
info.self=info
//判断一个标识符是否是对象
const isObject = (value) => {
//当null、object、array 都是显示为对象、function显示为函数
const valueType = typeof value
return (value!==null) && (valueType==="object"||valueType==="function")
}
const deepCopy=(originValue,map=new WeakMap())=>{
//当前是symbol 需要创建一个新的symbol
if (typeof originValue==='symbol'){
return Symbol(originValue.description)
}
// 如果是对象传入,需要一个完全的新对象,不是对象,则返回原数据
if (!isObject(originValue)){
return originValue
}
//当前值是set时
if (originValue instanceof Set){
const newSet = new Set()
for (const setItem of originValue) {
newSet.add(deepCopy(setItem))
}
return newSet
}
//当是数组是[] 当是对象时{}
if (map.get(originValue)){
return map.get(originValue)
}
const newObj=Array.isArray(originValue)? [] : {}
map.set(originValue,newObj)
// 对传入的对象进行遍历
for (const Key in originValue) {
//当是普通值,就直接引用赋值,当时对象,就进行递归调用赋值
newObj[Key] = deepCopy(originValue[Key],map)
}
//symbol循环引用
const symbolkeys = Object.getOwnPropertyDescriptor(originValue)
for (const symbolkey in symbolkeys) {
newObj[Symbol(symbolkeys.description)]=deepCopy(originValue[symbolkey],map)
}
return newObj
}
const newObj = deepCopy(info)
学从 codewhy