ホームページ  >  記事  >  ウェブフロントエンド  >  配列とオブジェクトの深いコピーと浅いコピーを実装する方法

配列とオブジェクトの深いコピーと浅いコピーを実装する方法

一个新手
一个新手オリジナル
2017-10-09 10:04:531899ブラウズ

前提:値を代入する際のプリミティブデータ型とオブジェクト型の違い

JavaScriptのデータ型はプリミティブデータ型とオブジェクト型に分けられます。この 2 つはメモリ内で異なる方法で保存されるため、割り当てに違いが生じます。それぞれ栗を取ってみましょう

  var x = 1;  var y = x;  //y获得了和x同样的值
  y = 2;
  console.log(x);  // 1

  var m = [1,2]; //m存放的是指向[1,2]这个数组对象的引用地址
  var n = m; //n也获得 [1,2]数组对象的引用地址
  n[0] = 3;
  console.log(m);  //[3,2]

上の栗からわかるように、元のデータ型が割り当てられると、割り当て後に実際のデータ値が与えられ、2 つの値はまったく同じであり、影響しません。オブジェクトタイプは元のデータの参照アドレスとして与えられますが、Shangli の配列のように、古いデータと新しいデータは本質的に同じデータオブジェクトであるため、相互に影響します

浅いコピーですか?

その名の通り、浅いコピーは表面的なコピー方法で、属性値がオブジェクト型の場合、オブジェクトデータへの参照のみがコピーされるため、古いデータと新しいデータが完全に分離されず影響を受けます。お互い。別の例を見てみましょう...

  //测试数据
  var array1 = ['a',1,true,{name:'lei',age:18}];

  //concat()  slice() 实现浅拷贝
  var array2 = array1.concat()

  //修改拷贝后的数据
  array2[0] = 'b';            //array1[0]是原始数据类型 所以是直接赋值的
  array2[3].name = 'zhang';   //array1[3]是对象数据类型 所以拷贝的是对象的引用,其实还是和原数组使用同一对象

  console.log(array1);   //  ['a',1,true,{name:'zhang',age:18}]

この例では、array2 は array1 の浅いコピー オブジェクトであり、配列要素は元のデータ型であり、相互に影響しません (array1[0])。ただし、array1[3] ] はオブジェクト タイプであり、引き続き相互に影響します。

浅いコピーの実装方法

    Shangli の array.concat() または array.slice() は、配列の浅いコピーを実装する特別な方法です。
  1. 自分で実装するにはどうすればよいですか?オブジェクト/配列の各属性をトラバースして、それを新しいオブジェクトに割り当てるだけで十分ではないでしょうか? 実装は次のとおりです
  2.   //实现浅拷贝
      function shallowCopy( target ){
        if(typeof target !== 'object') return ;
        //判断目标类型,来创建返回值
        var newObj = target instanceof Array ? [] : {};
    
        for(var item in target){
          //只复制元素自身的属性,不复制原型链上的
          if(target.hasOwnProperty(item)){
            newObj[item] = target[item]
          }
        }
    
        return newObj
      }
    
      //测试
    
      var test = [1,'a',{name:'lei',age:18}];
    
      var copy = shallowCopy(test);
      console.log(copy[2].name);   //lei
    
      copy[2].name = 'zhang';
      console.log(test[2].name);   //zhang   原数据也被修改
  3. 深いコピーとその実装

浅いコピーの説明から、次のようになります。基本的にディープコピーは「完全な」コピーであることを理解してください。コピー後、古いデータと新しいデータは完全に分離され、オブジェクトタイプの属性値を共有しなくなり、相互に影響を与えなくなります。

実装方法:

    トリッキーなメソッド JSON.parse(JSON.stringify(Obj))

  1. var test = [1,'a',{name:'lei',age:18}];
    
    var copy1 = JSON.parse(JSON.stringify(test));  //特殊方式
    
    console.log(copy1);
    
    copy1[2].name = 'zhang'
    console.log(test);   //[1,'a',{name:'lei',age:18}]  未受到影响
注: このメソッドは、属性値が関数であるオブジェクトをディープコピーすることはできません。自分で試すことができます。

2. ディープコピーの実装

考えてみれば、オブジェクトタイプの属性値を割り当てる際に、結果が完全な分離にならないはずなので、オブジェクトのコピー方法を変更する必要があります。属性値を入力し、その上で再度 deep を呼び出します。これにより、次のようにディープ コピーが実現されます。同じデータ オブジェクトが使用されるため、ディープ コピーが実装されます。この方法では、オブジェクト タイプの属性値を再帰的にディープ コピーして、直接の割り当てを回避します。

以上が配列とオブジェクトの深いコピーと浅いコピーを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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