JavaScriptオブジェクトのディープコピーの詳細説明

JavaScriptオブジェクトのディープコピーの詳細説明

ほとんどすべてのプログラミング言語では、オブジェクトは変数への参照として保存され、他の変数にコピーされます。JavaScript 言語にも同じことが当てはまります。したがって、コピーする単純な代入操作は、オブジェクト データの参照アドレスを転送するだけであり、オブジェクト内のすべてのプロパティの完全なコピーは作成されません。つまり、オブジェクトの 1 つが変更されると、もう 1 つの変数も変更されます。これは、これらの変数が本質的に同じオブジェクト参照を指しているためです。

let obj={
    a:1
};
let copyObj=obj;
obj.a=2;
//输出2
console.log(copyObj.a);

この言語機能は開発者にとって有益な場合があります。ただし、特定の開発シナリオでは、オブジェクトの「フル コピー」が必要になる場合があります。つまり、コピーされたオブジェクトとコピー前のオブジェクトは完全に独立しており、互いに影響しません。このプロセスは「ディープコピー」と呼ばれます。これに対応して、以前の単純な割り当てコピー操作は「浅いコピー」と呼ばれます。
ディープ コピーは、多くの JavaScript 面接官が尋ねる質問であり、手書きコードのトピックとして面接シナリオによく登場します。次の記事では、JavaScript でのディープ コピーの実装について詳しく分析します。

JSONコピー

このディープ コピー メソッドの原理は、JSON.parse 関数と JSON.stringify関数を使用してターゲット オブジェクトを一度エスケープし、それを再生成してコピーを実行することです。

//json拷贝,不能正确复制undefined、NaN、函数等数据类型
function jsonCopy(obj1){
    //{"a":[1,2],"b":{"a":"a","b":{"a":1}},"c":true,"d":null}
    let obj2=JSON.stringify(obj1);
    obj2=JSON.parse(obj2);
    return obj2;
}

let a={
    a:[1,2],
    b:{a:'a',b:{a:1}},
    c:true,
    d:null,
    e:undefined,
    f:function(a){return a+1;},
    g:NaN
};

let g=jsonCopy(a);
console.log(g);

プログラムの出力は次のとおりです。
ここに画像の説明を挿入
一般的なシナリオでは、JSON コピーがディープ コピーを作成する最も簡潔な方法です。ただし、上記の例からわかるように、JSON コピーはa オブジェクトf プロパティgプロパティを解決しません。これは、JSON レプリケーションが、未定義、NaN、関数、その他のデータ型など、一部の特定のデータ型を処理できないことを示しています (特定の状況はブラウザーによって異なります)。ただし、JSON コピーが次のデータ型のオブジェクト プロパティを正しく処理できることが保証されています:配列、プレーン オブジェクト、数値、文字列、ブール値

再帰コピー

このディープ コピー メソッドは、再帰関数を使用してターゲット オブジェクトの各属性をループし、各属性を新しいオブジェクトに再割り当てし、最後に新しいオブジェクトを返します。

//深拷贝
function deepCopy(obj1,obj2={}){
    for(let i in obj1){
        if(obj1.hasOwnProperty(i)){
            if(Array.isArray(obj1[i])){
                obj2[i]=[];
                deepCopy(obj1[i],obj2[i]);
            }else if(typeof obj1[i]==="function"){
                obj2[i]=obj1[i];
            }else if(obj1[i] instanceof Object){
                obj2[i]={};
                deepCopy(obj1[i],obj2[i]);
            }else{
                obj2[i]=obj1[i];
            }
        }
    }
    return obj2;
}

let a={
    a:[1,2],
    b:{a:'a',b:{a:1}},
    c:true,
    d:null,
    e:undefined,
    f:function(a){return a+1;},
    g:NaN
};

let f=deepCopy(a);
console.log(f);

プログラムの出力は次のとおりです。
ここに画像の説明を挿入
プログラムの出力からわかるように、再帰的コピーはすべてのデータ型のオブジェクト属性を正しく解決できます。ただし、再帰呼び出しでは実行時に関数スタックが保持されるため、ある程度のメモリとコンピューティングのパフォーマンスが低下します。ただし、通常の状況では、開発者がコピーする必要があるターゲット オブジェクトは、それほど深いオブジェクトではありません (通常、深さが約 100 レイヤーに達すると、再帰的コピーはフリーズします)。したがって、再帰的コピーは非常に優れたディープ コピーの実装です。ただし、注意すべき点が 1 つあります。ターゲット オブジェクトにFunction
データ型のプロパティがある場合、JavaScript 言語自体は開発者に関数を「完全にコピー」する適切な方法を提供していないため、関数はコピーできないということです。関数のコピーは依然として参照渡しです (いずれかの関数の可変プロパティが変更されると、もう一方のオブジェクトの関数プロパティも変更されます)。

おすすめ

転載: blog.csdn.net/yuhk231/article/details/89020288