前言 經常會在一些網站或博客看到“深克隆”,“淺克隆”這兩個名詞,其實這個很好理解,今天我們就在這裡分析一下 。 淺拷貝 我們先以一個例子來說明js淺拷貝: 上面顯然 的值會變為 12,這就是js淺拷貝。 淺拷貝只是拷貝的指向對象的指針,本質上還是指向同一個對象。 深拷貝 同樣我們還是以一個例子來說 ...
前言
經常會在一些網站或博客看到“深克隆”,“淺克隆”這兩個名詞,其實這個很好理解,今天我們就在這裡分析一下js深拷貝和淺拷貝
。
淺拷貝
我們先以一個例子來說明js淺拷貝:
var n = {a: 1, b: 2}
var m = n
m.a = 12
console.log(n.a) // ?
上面顯然 n.a
的值會變為 12,這就是js淺拷貝。淺拷貝只是拷貝的指向對象的指針,本質上還是指向同一個對象。
深拷貝
同樣我們還是以一個例子來說明啥叫 js deep clone
:
var n = {a: 1, b: 2}
var m = {a: n.a, b: n.b}
m.a = 12
console.log(n.a) // ?
上面的輸出結果顯然還是 1
,m 和 n 雖然所有的屬性和值全部相同,但是它們是兩個不同的對象,它們在堆記憶體中占據兩塊不同的記憶體地址,這就是深度拷貝。深度拷貝就是完全複製一個新的對象出來,它們在堆記憶體中完全占據兩個不同的記憶體地址。
js 實現深拷貝
簡單一維數據結構
- 手動直接賦值
上面的 深拷貝 例子
- 利用 ES6
Object.assign()
方法
const obj = {name: 'cc', age: 24}
const newObj = Object.assign({}, obj)
obj.name = 'cc1'
newObj.name ? // cc
二維的數據結構及以上
- 簡單粗暴的方式:
JSON.parse(JSON.stringify(obj))
。
缺點:它會對對於正則表達式類型、函數類型等無法進行深拷貝,而且會直接丟失相應的值,還有就是它會拋棄對象的 constructor
。
var obj = { a: {a: "cc"}, b: 123 }
var newObj = JSON.parse(JSON.stringify(obj))
newObj.b = 1234
console.log(obj) // {a: {a: 'cc'}, b: 123}
console.log(newObj); // {a: {a: 'cc'}, b: 1234}
- 利用 jQuery
// 淺拷貝
var newObj = $.extend({}, obj)
// 深拷貝
var newObj = $.extend(true, {}, obj) // 要求第一個參數必須為true
- 自己動手實現一個簡單深拷貝函數
function deepClone(obj){
if(typeof obj !== "object" || obj === null) return
let newObj = obj instanceof Array ? [] : {}
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key] = typeof obj[key] === "object" && obj[key] !== null ? deepClone(obj[key]) : obj[key]
}
}
return newObj
}
let obj = {a: 1, b: function(){}, c: {d: 2}}
deepClone(obj) // {a: 1, b: function(){}, c: {d: 2}}
對於深拷貝來說最常用的就是這些方法,當然還有其他的一些庫,比如 deepCopy
,lodash
等,這裡就不深究。