JavaScriptの深いコピーと浅いコピーについて簡単に説明します
2811 ワード
本文はgithubと掘金で収録した.掘金:https://juejin.im/post/5da5bc... github:https://github.com/Michael-lz...
深いコピー
深くコピーして変数値をコピーし、基本型以外の変数については、基本型変数に再帰してからコピーします.コピーされたオブジェクトは、元のオブジェクトから完全に分離され、互いに影響を与えず、1つのオブジェクトの変更は別のオブジェクトに影響を与えません.
浅いコピー
浅いコピーは、オブジェクトの各プロパティを順次コピーしますが、オブジェクトのプロパティ値が参照タイプの場合、実質的にその参照がコピーされ、参照が指す値が変更されると変化します.
区別する
浅いコピーと深いコピーは、参照データ型のみに適用されます.
1、浅いコピーはあるオブジェクトを指すポインタだけをコピーし、オブジェクト自体をコピーしないで、新しいオブジェクトと古いオブジェクトは同じメモリを共有します.2、深いコピーは、元のオブジェクトとメモリを共有せず、新しいオブジェクトを変更しても元のオブジェクトには変更されません.3、違い:浅いコピーはオブジェクトの第1層の属性のみをコピーし、深いコピーはオブジェクトの属性を再帰的にコピーすることができる.
以上の例から分かるように、データが参照データ型である場合
1.直接付与値は浅いコピー2、Objectに属する.assignは、データの第1層が基本データ型である場合、新しいオブジェクトと元のオブジェクトは互いに影響しないが、第1層の属性値が複雑なデータ型である場合、新しいオブジェクトと元のオブジェクトの属性値は同じメモリアドレスを指す.3、JSON.parse(JSON.stringify(obj))は深いコピーを実現できる
深いコピーの実装
1、JSON.parse(JSON.stringify(obj))しかしいくつかの欠陥が存在するオブジェクトの属性値が関数の場合、コピーできません. プロトタイプチェーンのプロパティは をコピーできません. Date,RegExpタイプのデータを正しく処理できない undefined は無視されます
2、一つのdeepClone関数を実現する基本データ型の場合、 に直接戻ります. RegExpまたはDateタイプの場合、対応するタイプ を返します.複雑なデータ型であれば再帰する. 循環参照を考慮する問題
深いコピー
深くコピーして変数値をコピーし、基本型以外の変数については、基本型変数に再帰してからコピーします.コピーされたオブジェクトは、元のオブジェクトから完全に分離され、互いに影響を与えず、1つのオブジェクトの変更は別のオブジェクトに影響を与えません.
浅いコピー
浅いコピーは、オブジェクトの各プロパティを順次コピーしますが、オブジェクトのプロパティ値が参照タイプの場合、実質的にその参照がコピーされ、参照が指す値が変更されると変化します.
区別する
浅いコピーと深いコピーは、参照データ型のみに適用されます.
1、浅いコピーはあるオブジェクトを指すポインタだけをコピーし、オブジェクト自体をコピーしないで、新しいオブジェクトと古いオブジェクトは同じメモリを共有します.2、深いコピーは、元のオブジェクトとメモリを共有せず、新しいオブジェクトを変更しても元のオブジェクトには変更されません.3、違い:浅いコピーはオブジェクトの第1層の属性のみをコピーし、深いコピーはオブジェクトの属性を再帰的にコピーすることができる.
let obj = {
name: 'Yvette',
age: 18,
hobbies: ['reading', 'photography']
}
let obj1 = obj
let obj2 = Object.assign({}, obj)
let obj3 = JSON.parse(JSON.stringify(obj))
obj.name = 'Jack'
obj.hobbies.push('coding')
console.log(obj) //{ name: 'Jack', age: 18,hobbies: [ 'reading', 'photography', 'coding' ] }
console.log(obj1) //{ name: 'Jack', age: 18,hobbies: [ 'reading', 'photography', 'coding' ] }
console.log(obj2) //{ name: 'Yvette', age: 18,hobbies: [ 'reading', 'photography', 'coding' ] }
console.log(obj3) //{ name: 'Yvette', age: 18,hobbies: [ 'reading', 'photography' ] }
以上の例から分かるように、データが参照データ型である場合
1.直接付与値は浅いコピー2、Objectに属する.assignは、データの第1層が基本データ型である場合、新しいオブジェクトと元のオブジェクトは互いに影響しないが、第1層の属性値が複雑なデータ型である場合、新しいオブジェクトと元のオブジェクトの属性値は同じメモリアドレスを指す.3、JSON.parse(JSON.stringify(obj))は深いコピーを実現できる
深いコピーの実装
1、JSON.parse(JSON.stringify(obj))しかしいくつかの欠陥が存在する
2、一つのdeepClone関数を実現する
function deepClone(obj, hash = new WeakMap()) {
//
if (obj instanceof RegExp) return new RegExp(obj)
if (obj instanceof Date) return new Date(obj)
if (obj === null || typeof obj !== 'object') {
// ,
return obj
}
if (hash.has(obj)) {
return hash.get(obj)
}
/**
* obj , obj.constructor [Function: Array]
* obj , obj.constructor [Function: Object]
*/
let t = new obj.constructor()
hash.set(obj, t)
for (let key in obj) {
//
if (obj.hasOwnProperty(key)) {
//
t[key] = deepClone(obj[key], hash)
}
}
return t
}