Modern Javascipt(深さ、浅さ)


データ型


Javascriptでは、データ型は基本型と参照型に分けられます.
前のデータ型では、詳細に議論しました.
Primitive Data Typeの特性とタイプ
一度に1つの値
  • しかありません.
  • は、固定メモリ領域を使用します.
  • タイプには、番号、String、Boolean、Undefind、Nullが含まれます.
  • 参照型(Non-Primitive DataType)の特徴とタイプ
  • は一度に複数の値を持つことができます.
  • は、複数の非固定の動的メモリ領域を利用する.
  • タイプには、オブジェクト、アレイ、および機能が含まれます.
  • 浅い放射


    浅いレプリケーションは参照型でのみ発生し、参照型プロファイルを含むアドレスをレプリケーションします.
    つまり、「値を含むアドレス」をコピーして「値」を変更すると、「値を含むアドレス」はそのままになり、元のデータとコピーデータの値は同じになります.

    図示されるように、obj2 = obj1obj2は、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も変更されます.obj2obj1を比較すると同じです.
    レプリケーションの値が元のデータを変更した場合、非常に大きな問題が発生する可能性があります.そのため、状況に応じて深さレプリケーションを使用する必要があります.

    ふかほうしゃ


    深いレプリケーションは、基本タイプと参照タイプで少し異なるものをレプリケーションする必要があります.
    デフォルトでは、値に関連付けられたアドレスが直接コピーされます.これ自体が深度コピーです.
    リファレンスフォーマットでは、値を含むアドレスを元のデータとは異なるメモリアドレスにコピーする必要があります.
    値を別の新しい値に再割り当てすると、Javascriptは新しいメモリアドレスに配置されます.(同じ値に同じアドレスを使用)

    きほんふかふくせい


    デフォルトでは、基本データ型のレプリケーションは深度レプリケーションです.

    図に示すように、複製abは、値が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を使用する必要がある場合があります.