ホームページ  >  記事  >  ウェブフロントエンド  >  jsでの浅いコピーと深いコピーの実装方法は何ですか? (要約)

jsでの浅いコピーと深いコピーの実装方法は何ですか? (要約)

不言
不言オリジナル
2018-09-18 14:58:227759ブラウズ

この記事でわかることは、jsにおける浅いコピーと深いコピーの実装方法とは何なのかということです。 (要約) 必要な友人が参考になれば幸いです。

js には、string、number、boolean、null、undefind の 5 つの基本データ型があります。これら 5 種類の割り当ては値の転送です。オブジェクトの割り当ては、オブジェクト アドレスへの参照を割り当てることです。このとき、オブジェクト内のプロパティまたは値を変更すると、オブジェクトへのすべての参照の値が変更されます。オブジェクトへの参照をコピーするのではなく、実際に新しいオブジェクトをコピーしたい場合は、オブジェクトのディープ コピーを使用する必要があります。

浅いコピー実装

1.「=」割り当て。

あまり言う必要はありませんが、最も基本的な代入方法は、単にオブジェクトへの参照を割り当てることです。

2.Object.assign()

Object.assign は ES6 の新しい関数です。 Object.assign() メソッドは、ソース オブジェクト自体の列挙可能なプロパティを任意の数だけターゲット オブジェクトにコピーし、ターゲット オブジェクトを返すことができます。ただし、Object.assign() は浅いコピーを実行し、オブジェクト自体ではなく、オブジェクトのプロパティへの参照をコピーします。

Object.assign(target, ...sources)

パラメータ:
target: ターゲット オブジェクト。
sources: 任意の数のソース オブジェクト。
戻り値: 対象のオブジェクトが返されます。

var obj = { a: {a: "hello", b: 21} };
var initalObj = Object.assign({}, obj);

initalObj.a.a = "changed";
console.log(obj.a.a); // "changed"

次のことに注意してください:
Object.assign() は、次のように 1 つのレイヤーのディープ コピーを処理できます:

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = Object.assign({}, obj1);
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- 沒被改到
console.log(obj2);
// { a: 10, b: 100, c: 30 }

ディープ コピー

1。手動コピー

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- 沒被改到
console.log(obj2);
// { a: 10, b: 100, c: 30 }

2. JSON 文字列変換

JSON.stringify を使用してオブジェクトを文字列に変換し、JSON.parse を使用して文字列を新しいオブジェクトに変換します。

var obj1 = { body: { a: 10 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.body.a = 20;
console.log(obj1);
// { body: { a: 10 } } <-- 沒被改到
console.log(obj2);
// { body: { a: 20 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// false

これは真のディープ コピーです。この方法はシンプルで使いやすいです。

しかし、このメソッドには、オブジェクトのコンストラクターが破棄されるなど、多くの欠点もあります。つまり、ディープ コピー後は、オブジェクトの元のコンストラクターが何であっても、ディープ コピー後はオブジェクトになります。

このメソッドが正しく処理できるオブジェクトは、Number、String、Boolean、Array、およびフラット オブジェクト、つまり、json で直接表現できるデータ構造のみです。 RegExp オブジェクトをこの方法でディープ コピーすることはできません。

つまり、この方法で使用できるのは JSON 形式に変換できるオブジェクトのみです。関数は JSON に変換できません。

var obj1 = { fun: function(){ console.log(123) } };
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(typeof obj1.fun);
// 'function'
console.log(typeof obj2.fun);
// 'undefined' <-- 没复制

3. 再帰コピー

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : {};            
      arguments.callee(prop, obj[i]);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}
var str = {};
var obj = { a: {a: "hello", b: 21} };
deepClone(obj, str);
console.log(str.a);

4. Object.create() メソッドを使用します

ディープ コピー効果を実現するには、var newObj = Object.create(oldObj) を直接使用します。 。

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];        // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
    } else {
      obj[i] = prop;
    }
  }    
  return obj;
}

5.jquery

jquery は、ディープ コピーに使用できる $.extend を提供します。

var $ = require('jquery');
var obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
var obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f);
// false

6. サードパーティ関数

lodash など、ディープ コピー関数を備えた他のサードパーティ関数ライブラリもあります。

以上がjsでの浅いコピーと深いコピーの実装方法は何ですか? (要約)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。