本文將手動實現(xiàn)引用類型的深拷貝
關于值類型與引用類型可閱讀下方文章:
JS基礎類型直通車:
Js基礎知識-變量類型
Js基礎知識-typeof運算符
let obj1={
name:'王',
age:23,
address:{
city:'河南省鄭州市'
},
hobby:['play','eat']
}
let obj2=obj1
console.log(obj1.name) // 王
obj2.name='李'
console.log(obj1.name) // 李
由于直接將obj1直接賦值給了obj2,此時他們的指針地址是相同的,所以當obj2改變時,obj1的值也會改變。
如何將obj1賦值給obj2,修改obj2的值obj1得值不會改變?
- 創(chuàng)建方法deepClone,將返回一個值作為方法的返回值
/**
* 深度克隆
* @param {object} obj 需要克隆的對象/數組
*/
function deepClone(obj={}){
return obj
}
- 檢查傳入的參數類型是否為引用類型,不是的話將參數直接返回
/**
* 深度克隆
* @param {object} obj 需要克隆的對象/數組
*/
function deepClone(obj={}){
if(typeof obj!=='object'||obj==null){
return obj
}
}
- 處理參數為引用類型,檢查是否為數組,定義新的變量
/**
* 深度克隆
* @param {object} obj 需要克隆的對象/數組
*/
function deepClone(obj={}){
if(typeof obj!=='object'||obj==null){
return obj
}
let result // 將要返回的變量
if(obj instanceof Array){
result=[] // 如果Obj為數組,則將返回定義為空數組
}else{
result={} // 如果Obj為對象,則將返回定義為空對象
}
}
- 遍歷賦值
會用到遞歸,如果不清楚可以將每一個obj的值進行打印。
/**
* 深度克隆
* @param {object} obj 需要克隆的對象/數組
*/
function deepClone(obj={}){
if(typeof obj!=='object'||obj==null){
return obj
}
let result // 將要返回的變量
if(obj instanceof Array){
result=[] // 如果Obj為數組,則將返回定義為空數組
}else{
result={} // 如果Obj為對象,則將返回定義為空對象
}
// forin可以用于對象和數組的遍歷
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key]=deepClone(obj[key]) // 使用遞歸
}
}
}
- 再次聲明測試
/**
* 深度克隆
* @param {object} obj 需要克隆的對象/數組
*/
function deepClone(obj={}){
console.log(obj)
//obj每次的值
//王 23 {city: "河南省鄭州市"} 河南省鄭州市 ["play", "eat"] play eat
if(typeof obj!=='object'||obj==null){
return obj
}
let result // 將要返回的變量
if(obj instanceof Array){
result=[] // 如果Obj為數組,則將返回定義為空數組
}else{
result={} // 如果Obj為對象,則將返回定義為空對象
}
// forin可以用于對象和數組的遍歷
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key]=deepClone(obj[key]) // 使用遞歸
}
}
return result
}
let obj2=deepClone(obj1)
obj2.name='李'
console.log(obj1.name,obj2.name) // 王 李
經過手動實現(xiàn)深度拷貝后就會發(fā)現(xiàn),當改變obj2的值后,obj1并不會發(fā)生改變。
上一章 : Js基礎知識-typeof運算符