淺拷貝與深拷貝的區別
1、資料型別:
* 資料分為基本的資料型別(String, Number, boolean, Null, Undefined)和物件資料型別
- 基本資料型別:
特點: 儲存的是該物件的實際資料
- 物件資料型別:
特點: 儲存的是該物件在棧中引用,真實的資料存放在堆記憶體裡
2、複製資料
- 基本資料型別存放的就是實際的資料,可直接複製
let number2 = 2;
let number1 = number2;
- 物件資料存放的是物件在棧記憶體的引用,直接複製的是物件的引用
let obj = {username: 'kobe'}
let obj1 = obj; // obj1 複製了obj在棧記憶體的引用
3、為什麼要分深淺拷貝
淺拷貝:原始型別為值傳遞,物件型別仍為引用傳遞。
深拷貝(物件/陣列):所有元素或屬性均完全複製,與原物件完全脫離,也就是說所有對於新物件的修改都不會反映到原物件中。
顯然,淺拷貝會帶來一個很大的問題。就是,如果我複製的值是一個引用地址,那麼我通過一個變數去修改這個物件,會導致所有該物件的引用都發生變化。
// Object.assign() 並不是深拷貝
object.assign(target, source1, source2....) 將源物件的屬性複製到目標物件上
let obj1 = {
n: 12,
m: 'abc'
}
let obj2={}
object.assign(obj2, obj1)
console.log(obj2)
4、常用的拷貝技術
1). arr.concat(): 陣列淺拷貝
2). arr.slice(): 陣列淺拷貝
3). JSON.parse(JSON.stringify(arr/obj)): 陣列或物件深拷貝, 但不能處理函式資料
4). 淺拷貝包含函式資料的物件/陣列
5). 深拷貝包含函式資料的物件/陣列
1.基本資料型別的淺拷貝
let a = 'abc'
let b = a
b = '123'
console.log(a) abc
console.log(b) // 沒有對原來的資料影響
2.物件資料型別的淺拷貝
let obj = {
name: 'MsYangyang',
age: 18,
sex: {
option1: '男'
option2: '女'
}
}
let obj2 = obj // obj2儲存的是obj的地址值
obj2.name = 'Li' // 本質上修改了原物件的屬性值
console.log(obj) Li
let obj3 = {} /新建的物件
object.assign(obj3, obj)
obj3.name='xxxx'
obj3.sex.option1='不男不女'
console.log(obj) Li 不男不女,女
3.函式的克隆
let fun1 = function () {
console.log('1111')
}
let fun2 = fun1
fun2 = function () {
console.log('2222')
}
fun1() 1111 // 沒有對原來的物件產生影響 :函式的克隆會在堆空間單獨開闢一片空間 與原來的物件互不影響
fun2() 2222
深拷貝(本質:建立一個新的 {} 或 [] )
// 準備工作 :如何正確判斷判斷資料的型別?
let obj3 = []
console.log(Object.prototype.toString.call(obj3))
// 建立一個用來判斷資料型別的函式
function getObjClass(obj) {
let result = Object.prototype.toString.call(obj).slice(8, -1) //Array
if (result === 'Undefined') {
return 'Undefined'
}else if (result === 'Null') {
return 'Null'
}else {
return result
}
}
// 建立一個深度遍歷物件/陣列的函式
function deepClone(obj) {
let objClass = getObjClass(obj)
let result
if(objClass === 'Object') {
result = {}
}else if (objClass === 'Array') {
result = []
}else {
return obj // 如果是其他資料型別就直接返回 不進行復制
}
// 遍歷目標物件
for(let key in obj) {
let value = obj[key]
if (getObjClass(value) === 'Object') {
result[key] = deepClone(value)
}else if (getObjClass(value) === 'Array') {
result[key] = deepClone(value)
}else {
result[key] = obj[key]
}
}
return result
}
let obj4 = {
name: 'haha',
age: 20,
sex: {
option1: '男',
option2: '女'
}
}
let obj5 = deepClone(obj4)
console.log(obj5, 'obj5')
obj5.sex.option1 = '不男不女'
console.log(obj4, 'obj4')