JS物件的引用複製和資料複製

2021-09-27 08:03:52 字數 2384 閱讀 8561

js物件分為兩類,一類為基礎型別物件,包括字串(string),數值(number),布林值(boolean),null(空),undefined(未定義)。另一類為合成物件,又叫做引用型別物件,包括陣列(array),物件(object),函式(function)。

基礎型別物件儲存的是物件的實際資料,引用型別物件儲存的是物件的引用位址,而把物件的實際內容單獨存放,因為引用物件通常比較龐大,這是資料開銷和記憶體開銷優化的手段。

基礎物件的賦值,實際複製的是物件本身的資料:

let a = 5

let b = a

b = 1

console.log(a) // => 5

console.log(b) // => 1

// a為基礎型別物件,儲存的為資料本身,所以賦值給b後,b儲存的也是資料本身

// 資料被複製為兩份,a,b各乙份,a,b各自的操作僅對自身有效.

let a = new array(1,2,3)

let b = a

let c = a

b.push(4)

console.log(a) // => [1,2,3,4]

console.log(b) // => [1,2,3,4]

console.log(c) // => [1,2,3,4]

c[0] = 5

console.log(a) // => [5,2,3,4]

console.log(b) // => [5,2,3,4]

console.log(c) // => [5,2,3,4]

// 複合型物件即引用型物件複製的是物件的引用,b,c,分別複製了a的物件引用

// 實際a,b,c擁有相同的引用位址,位址指向的是同乙個物件

// 當b,c分別做物件操作時,實際操作的仍舊是同一物件

如何避免引用型物件複製造成的資料關聯操作,達到真正賦值的目的:

// 通過物件資料的序列化和反序列化達到賦值的目的

let a =

let b = json.stringify(a) // 序列化a賦值給b

let c = json.parse(b) // 反序列化b賦值給c

// 當然可以一步寫完,完全沒必要有b => let c = json.parse(json.stringify(a))

c.x = 5

console.log(c) // =>

console.log(a) // =>

// a的值成功的賦值給了c,並且c的操作已經對a沒有影響了

一般操作建議封裝函式批量處理此類問題,因為比較常見,處理方法採用遞迴迴圈讀取物件屬性直至內部再無引用型物件存在:

// 所有物件在寫方法時都要當作為多屬性物件,且物件中含有鍵指向其他物件

let obj =

}let x = (obj) =>

let newobj = {}

for (let key in obj)

return newobj;

}// 呼叫方法:

let newobj = x(obj)

以上僅考慮了物件,且僅考慮了物件的內部屬性為物件的情況,實際使用中,物件內部的屬性可能指向的是乙個物件,也可能是乙個陣列又或者是乙個函式,由於函式可以直接轉殖複製,不會關聯變化,暫不在考慮範圍內。不論是物件或者陣列或都會導致賦值的不正確。同理,由於js中陣列什麼都能存,陣列中可能存放有物件,陣列又或者是函式等,這些都需要遞迴查詢。

對於物件或者陣列處理方式其實也很簡單,在上面示例中加入陣列的判斷即可。if typeof === object => 走物件賦值的邏輯,同時遞迴檢查,if instanceof(array) => 走陣列的賦值邏輯,同時遞迴檢查即可, typeof無法檢查陣列。

function copy (obj) 

let newarr =

let newobj = {}

if (obj instanceof array)

return newarr

} else

return newobj

}}let obj = ,9]

}},

f: [5,6,7]

}let c = copy(obj)

c.f[0] = 10

c.c.d = 'hello world'

c.c.g.h = 'woo'

c.c.g.i[0].j = 12

console.log(c) // => },f: [ 10, 6, 7 ] }

console.log(obj) // => },f: [ 5, 6, 7 ] }

賦值後操作相互不影響,目的已經達到。

js物件複製

淺複製 var obj var obj1 var obj2 object.assign obj var obj var obj1 var obj2 object.assign obj obj.c.push 2 var obj var copyobj json parse json stringify...

物件和陣列的淺複製和深複製

之前踩過一些複製的坑,現在總結一下記錄下來,供以後開發時參考,相信對其他人也有用。淺複製 一般用object.assign,如果支援es6的話也可以用新語法 const obj 可以用object.assign const obj2 object.assign obj1 es6的解構 const o...

js陣列賦值 引用 深複製 淺複製

如 var a 1,2,3,4 var b b a 這個不是把值賦值過去而是b作為a的引用,b改變的是a 如何b指向的是乙個新陣列,a把元素值全部賦值過去?1 普通陣列可以使用varb concat a 2 我遇到乙個jquery物件型別的陣列是 object array 型別,其拼接的陣列字串為 ...