js対象は浅いコピーと深いコピーです.

5049 ワード

js対象は浅いコピーと深いコピーです.
  • javascriptではObject、Arayは参照タイプであり、スタックメモリにメモリアドレス、メモリ記憶値を記憶するため、参照タイプのコピーには浅いコピー、深いコピーが存在する.以下、例によって説明する.
  • 基本タイプと参照タイプの違いから、関数値伝達の違いに注意して、ここでは詳細に説明しない.
  • 浅いコピー
  • オブジェクトが値タイプの属性だけであれば、拡張子(…)またはObject.assign(…)を使用して
  • をコピーすることができます.
    
    var obj = { foo: "foo", bar: "bar" };
    var copy = { ...obj }; // Object { foo: "foo", bar: "bar" }
    
    
    var obj = { foo: "foo", bar: "bar" };
    var copy = Object.assign({}, obj); // Object { foo: "foo", bar: "bar" }
    
  • において、上記の2つの方法は、属性値を複数のソースオブジェクトからターゲットオブジェクトにコピーするために使用されてもよいことに留意されたい.例
  • var obj1 = { foo: "foo" };
    var obj2 = { bar: "bar" };
    
    var copySpread = { ...obj1, ...obj2 }; // Object { foo: "foo", bar: "bar" }
    var copyAssign = Object.assign({}, obj1, obj2); // Object { foo: "foo", bar: "bar" }
    
  • 上記の方法の問題は、属性自体のオブジェクトを有するオブジェクトに対して、参照のみをコピーすることである.例
  • var foo = { a: 0 , b: { c: 0 } };
    var copy = { ...foo };
    
    copy.a = 1;
    copy.b.c = 2;
    
    console.dir(foo); // { a: 0, b: { c: 2 } }
    console.dir(copy); // { a: 1, b: { c: 2 } }
    console.log(copy.b === foo.b) // true
    
    コピー
  • は、JSONを利用してオブジェクトを文字列に並べ、その後、その逆順序化する.
  • var obj = { a: 0, b: { c: 0 } };
    var copy = JSON.parse(JSON.stringify(obj));
    console.log(copy.a === obj.b) // false
    
  • 残念なことに、この方法は、ソースオブジェクトがプログレッシブ値タイプを含み、循環参照がない場合にのみ有効である.
  • 
    var obj = { a: 0, b: { c: 0 }, d: function() {console.log('------>')} };
    var copy = JSON.parse(JSON.stringify(obj));
    
    console.log(copy) // {a: 0, b: {…}}
    
    
    var obj = { a: 0, b: { c: 0 }, f: new Date() };
    var copy = JSON.parse(JSON.stringify(obj));
    console.log(copy) // {a: 0, b: {…}, f: "2018-12-07T08:11:48.210Z"}
    
    
  • NODE.JSの深度コピー
  • は8.0.0版から始まり、Node.jsは構造クローニングと互換性のあるプログレッシブAPIを提供している.
  • は、8.0.0以下のバージョンまたはより安定した実装のために、lodashのclone Deep方法を使用することができ、この方法も構造化クローニングアルゴリズムに基づく.
  • const v8 = require('v8');
    const buf = v8.serialize({a: 'foo', b: new Date()});
    const cloned = v8.deserialize(buf);
    cloned.b.getMonth();
    
    結び目
  • とにかく、Javascriptでコピーするオブジェクトの最適なアルゴリズムは、コピーするオブジェクトのコンテキストとタイプに大きく依存します.lodashは汎用深層コピー機能の最も安全な選択ですが、簡単な適用日コピーの深さコピーを書くこともできます.
  • 適用日の深コピー実現例
  • function deepClone(obj) {
      var copy;
    
      // Handle the 3 simple types, and null or undefined
      if (null == obj || "object" != typeof obj) return obj;
    
      // Handle Date
      if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
      }
    
      // Handle Array
      if (obj instanceof Array) {
        copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = deepClone(obj[i]);
        }
        return copy;
      }
    
      // Handle Function
      if (obj instanceof Function) {
        copy = function() {
          return obj.apply(this, arguments);
        }
        return copy;
      }
    
      // Handle Object
      if (obj instanceof Object) {
          copy = {};
          for (var attr in obj) {
              if (obj.hasOwnProperty(attr)) copy[attr] = deepClone(obj[attr]);
          }
          return copy;
      }
    
      throw new Error("Unable to copy obj as type isn't supported " + obj.constructor.name);
    }
    
    参照リンク
  • オブジェクト深度コピー