Modern Javascipt(深さ、浅さ)
21015 ワード
データ型
Javascriptでは、データ型は基本型と参照型に分けられます.
前のデータ型では、詳細に議論しました.
Primitive Data Typeの特性とタイプ
一度に1つの値
浅い放射
浅いレプリケーションは参照型でのみ発生し、参照型プロファイルを含むアドレスをレプリケーションします.
つまり、「値を含むアドレス」をコピーして「値」を変更すると、「値を含むアドレス」はそのままになり、元のデータとコピーデータの値は同じになります.
図示されるように、obj2 = obj1
〜obj2
は、obj1
のPropertiesを含むアドレス@1000を複製する.let obj1 = {
a : 10,
b : 'abc'
};
obj2 = obj1
console.log(obj2 === obj1) // true
console.log(obj2.a === obj1.a) //true
obj2.a = 20;
console.log(obj1.a) // 20
したがって、コピーされたobj2
のpropertyを変更すると、obj1
のpropertyも変更されます.obj2
とobj1
を比較すると同じです.
レプリケーションの値が元のデータを変更した場合、非常に大きな問題が発生する可能性があります.そのため、状況に応じて深さレプリケーションを使用する必要があります.
ふかほうしゃ
深いレプリケーションは、基本タイプと参照タイプで少し異なるものをレプリケーションする必要があります.
デフォルトでは、値に関連付けられたアドレスが直接コピーされます.これ自体が深度コピーです.
リファレンスフォーマットでは、値を含むアドレスを元のデータとは異なるメモリアドレスにコピーする必要があります.
値を別の新しい値に再割り当てすると、Javascriptは新しいメモリアドレスに配置されます.(同じ値に同じアドレスを使用)
きほんふかふくせい
デフォルトでは、基本データ型のレプリケーションは深度レプリケーションです.
図に示すように、複製a
のb
は、値が100のアドレス@1001を複製する.
すなわち、値(100)のアドレス(@1001)をコピーする.let a = 100;
b = a;
console.log(a === b); // true
b = 200;
console.log(a); // 100
console.log(a === b); // false
デフォルトでは、値のアドレスをコピーすると、識別子に新しい値を割り当てると、新しい値のアドレスがメモリに接続されます.
参照シェイプを深くコピー
では、重要な参照型の深さコピーを見てみましょう.
理論的には,浅いレプリケーションから元の参照型とレプリケーション参照型の変化は,それらのアドレス値が同じであるためである.
簡単に言えば、同じ値を含むアドレス値を参照する必要はありません(下図では@1000).
図中、obj1
およびobj2
は、異なるアドレス値を指す.obj2.a
の値を変更すると、obj1.a
の値は次の図のように変更されません.
参照モデルの複数の深さコピーを見てみましょう.
直接再帰関数による深さレプリケーション関数の実現
上記の理論に基づいて,深さ複製を直接実施する.const copyObjectDeep = (obj) => {
if(obj === null || typeof obj !== "object"){
return obj;
}
let copyResult = {}
for (let prop in obj){
copyResult[prop] = copyObjectDeep(obj[prop]);
}
return copyResult;
}
const obj = {
a: 10,
b: {
c: null,
d: [1, 2]
},
};
const obj2 = copyObjctDeep(obj);
console.log(obj === obj2) // false
obj2.a = 1000;
console.log(obj, obj2); // {a: 10, b: {…}} {a: 1000, b: {…}}
obj2.b.c = 200;
console.log(obj.b, obj2.b); // {c: null, d: Array(2)} {c: 200, d: {…}}
前述の理論に示されるように、ソースオブジェクトobj
のすべてのプロパティは、再帰関数によって複製され、新しいオブジェクトresult
に入れられる.
すなわち,全く異なるアドレスを参照するために深いレプリケーションを行った.
したがって、コピーされたobj2
のプロパティを変更しても元のオブジェクトには影響しません.
JSONによる深度コピー
原理はJSON対象です.文字列()メソッドに変換します.
再JSONparse()メソッドで文字列をオブジェクトに変換します.
これにより、既存のアドレスと同じ値しか得られません.
理論的に深く複製する.const copyObjectUsingJSON = (obj) => {
return JSON.parse(JSON.stringify(obj));
}
const obj = {
a: 10,
b: {
c: null,
func1 : function () { console.log("함수"); },
},
func2 : function () { console.log("함수2"); },
};
const obj2 = copyObjectUsingJSON(obj);
console.log(obj === obj2) // false
obj2.a = 1000;
console.log(obj, obj2); // {a: 10, b: {…}} {a: 1000, b: {…}, func2: f}
obj2.b.c = 200;
console.log(obj.b, obj2.b); // {c: null, func1: ƒ} {c: 200}
JSONによる深度コピーにはいくつかの注意点があります.
let obj1 = {
a : 10,
b : 'abc'
};
obj2 = obj1
console.log(obj2 === obj1) // true
console.log(obj2.a === obj1.a) //true
obj2.a = 20;
console.log(obj1.a) // 20
深いレプリケーションは、基本タイプと参照タイプで少し異なるものをレプリケーションする必要があります.
デフォルトでは、値に関連付けられたアドレスが直接コピーされます.これ自体が深度コピーです.
リファレンスフォーマットでは、値を含むアドレスを元のデータとは異なるメモリアドレスにコピーする必要があります.
値を別の新しい値に再割り当てすると、Javascriptは新しいメモリアドレスに配置されます.(同じ値に同じアドレスを使用)
きほんふかふくせい
デフォルトでは、基本データ型のレプリケーションは深度レプリケーションです.
図に示すように、複製
a
のb
は、値が100のアドレス@1001を複製する.すなわち、値(100)のアドレス(@1001)をコピーする.
let a = 100;
b = a;
console.log(a === b); // true
b = 200;
console.log(a); // 100
console.log(a === b); // false
デフォルトでは、値のアドレスをコピーすると、識別子に新しい値を割り当てると、新しい値のアドレスがメモリに接続されます.参照シェイプを深くコピー
では、重要な参照型の深さコピーを見てみましょう.
理論的には,浅いレプリケーションから元の参照型とレプリケーション参照型の変化は,それらのアドレス値が同じであるためである.
簡単に言えば、同じ値を含むアドレス値を参照する必要はありません(下図では@1000).
図中、
obj1
およびobj2
は、異なるアドレス値を指す.obj2.a
の値を変更すると、obj1.a
の値は次の図のように変更されません.参照モデルの複数の深さコピーを見てみましょう.
直接再帰関数による深さレプリケーション関数の実現
上記の理論に基づいて,深さ複製を直接実施する.
const copyObjectDeep = (obj) => {
if(obj === null || typeof obj !== "object"){
return obj;
}
let copyResult = {}
for (let prop in obj){
copyResult[prop] = copyObjectDeep(obj[prop]);
}
return copyResult;
}
const obj = {
a: 10,
b: {
c: null,
d: [1, 2]
},
};
const obj2 = copyObjctDeep(obj);
console.log(obj === obj2) // false
obj2.a = 1000;
console.log(obj, obj2); // {a: 10, b: {…}} {a: 1000, b: {…}}
obj2.b.c = 200;
console.log(obj.b, obj2.b); // {c: null, d: Array(2)} {c: 200, d: {…}}
前述の理論に示されるように、ソースオブジェクトobj
のすべてのプロパティは、再帰関数によって複製され、新しいオブジェクトresult
に入れられる.すなわち,全く異なるアドレスを参照するために深いレプリケーションを行った.
したがって、コピーされた
obj2
のプロパティを変更しても元のオブジェクトには影響しません.JSONによる深度コピー
原理はJSON対象です.文字列()メソッドに変換します.
再JSONparse()メソッドで文字列をオブジェクトに変換します.
これにより、既存のアドレスと同じ値しか得られません.
理論的に深く複製する.
const copyObjectUsingJSON = (obj) => {
return JSON.parse(JSON.stringify(obj));
}
const obj = {
a: 10,
b: {
c: null,
func1 : function () { console.log("함수"); },
},
func2 : function () { console.log("함수2"); },
};
const obj2 = copyObjectUsingJSON(obj);
console.log(obj === obj2) // false
obj2.a = 1000;
console.log(obj, obj2); // {a: 10, b: {…}} {a: 1000, b: {…}, func2: f}
obj2.b.c = 200;
console.log(obj.b, obj2.b); // {c: null, func1: ƒ} {c: 200}
JSONによる深度コピーにはいくつかの注意点があります.function、proto、getter/setterなど、JSONに変更できないすべてのPropertyを無視します.
処理速度は他の方法より遅い.
拡張演算子による深度コピー
深い複製はspread演算子
...obj
を使用して行うことができる.const obj = {
a: 10,
b: {
c: null,
func1 : function () { console.log("함수"); },
},
};
const obj2 = {...obj};
console.log(obj === obj2) // false
obj2.a = 1000;
console.log(obj, obj2); // {a: 10, b: {…}} {a: 1000, b: {…}}
obj2.b.c = 200;
console.log(obj.b, obj2.b); // {c: 200, func1: ƒ} {c: 200, func1: ƒ}
spread演算子を使用すると、深度コピーを非常に簡単に行うことができます.サンプルコードでご覧のように、これは大きな問題です.
拡散演算子による深度コピーは、ネストされたオブジェクトの浅いコピーを意味します.
だから状況に応じて使います.
lodashモジュールのclonedeepを使用して深さレプリケーションを行う
直接実施することは困難であり、
JSONでは関数のようなデータ型をコピーできません.
拡張演算子を使用すると、ネストされたオブジェクトを深くコピーできません.
私たちは良いモジュールを持っています.
lodash
モジュールのcloneDeep()
メソッド.// 먼저 lodash 모듈을 설치해줍니다.
& npm i lodash
const lodash = require("lodash");
const obj = {
a: 10,
b: {
c: null,
func1 : function () { console.log("함수"); },
},
};
const obj2 = lodash.cloneDeep(obj);
console.log(obj === obj2) // false
obj2.a = 1000;
console.log(obj, obj2); // {a: 10, b: {…}} {a: 1000, b: {…}}
obj2.b.c = 200;
console.log(obj.b, obj2.b); // {c: null, func1: ƒ} {c: 200, func1: ƒ}
これはこれまで知られてきた最も簡単で、最も欠点のない方法です.深度コピーを行うには、lodashを使用する必要がある場合があります.
Reference
この問題について(Modern Javascipt(深さ、浅さ)), 我々は、より多くの情報をここで見つけました https://velog.io/@dev-yun/Modern-Javascipt-깊은복사-얕은복사テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol