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 型別,其拼接的陣列字串為 ...