シャローコピーとディープコピーは通常、参照データ型にのみ適用されます。
I. コンセプト
var obj = {name: 'tanakasan'};
var obj2 = obj;
console.log(obj2.name); // 'tanakasan'
obj2.name = 'Lisi';
console.log(obj.name); //'Lisi'
特定のオブジェクトを指すオブジェクトとオブジェクトだけをコピーすると、古いオブジェクトと新しいオブジェクトはそのままで、参照される変数だけが異なり、それらのいずれかに変更を加えると、もう一方にも影響します。
それは別のオブジェクトを作成し、メモリはまったく同じ、元のオブジェクトと新しいオブジェクトを変更し、新しいオブジェクトは、元のオブジェクトを変更しません。
第二に、ディープコピーの実装
JSON.stringify()は現在、ディープコピーの開発プロセスで最も一般的に使用され、原理は、オブジェクトをJSON文字列にシリアライズし、オブジェクトの内容を文字列の形式にしてメモリに保存し、JSON.parse()新しいオブジェクトにJSON文字列をデシリアライズすることです。
function deepClone(obj) { return JSON.parse(JSON.stringify(obj)); } var a = [0, 1, [2], 3]; var b = deepClone(a); b[0] = 1; b[2][0] = 3; console.log(a);//[0, 1, [2], 3] console.log(b);//[1, 1, [3], 3]
1) コピーされたオブジェクトの値にfunction,undefined,symbolがある場合、JSON.stringify()でシリアライズした後、JSON文字列からキーと値のペアが消えます;
2) 列挙不可能なプロパティをコピーできない、オブジェクトのプロトタイプチェーンをコピーできない
3) コピー日付参照型は文字列になります。
4) RegExp参照型をコピーすると空のオブジェクトになります。
5) オブジェクトにNaN、Infinity、-Infinityが含まれる場合、シリアライズ結果はNULLになります。
jQuery.extend()関数は、1つ以上のオブジェクトの内容をターゲットオブジェクトにマージするために使用します。
.extend( [DEEP ], target, object1 [, objectN ] );
第1引数にfalseを渡すことはサポートされていません。
var a = [0, 1, [2], 3];
var b = $.extend(true, [], a);
b[0] = 1;
b[2][0] = 3 ;
console.log(a);//[0, 1, [2], 3]
console.log(b);//[1, 1, [3], 3]
このメソッドは、オブジェクトにプライマリ属性しかなく、セカンダリ属性がない場合はディープコピーですが、オブジェクトにオブジェクトがある場合は、セカンダリ属性の後に、このメソッドはシャローコピーになります。
lodashライブラリはディープコピーを実装するためにlodash.cloneDeep()を提供します。
//配列、オブジェクトのディープコピーには再帰的な方法を使う。{ //コピーが配列かオブジェクトかを判断し、配列なら配列のコピーを、オブジェクトならオブジェクトのコピーを作る let objClone= Array.isArray(obj) ? [] : {}; //ディープコピーはnullにはできず、オブジェクトかif (obj&& typeof obj === "object") { for (let key in obj) { if (obj.hasOwnProperty(key)) { // objの子要素がオブジェクトかどうかを判定し、オブジェクトであれば再帰的にコピーする。[key] && typeof obj[key] === "object") { objClone[key] = deepClone(obj[key]); } else { objClone[key] = obj[key]; } } } } return objClone;}
var a = [1,2,3,4,[5,6]] var b = deepClone(a) // [1,2,3,4,[5,6]] a[4] [0]= 6 console.log(a)// [1,2,3,4,[6,6]]