javascriptの浅いコピー、深いコピー

2884 ワード

以前はjavascriptに対して浅いコピーで和深にコピーしたのは生半可です.今はよく整理してください.
まず、参照型の変数について知っています.変数が実際に記憶されているのは、メモリのアドレスを指している変数のポインタです.以下のコードの中で
var a = {
  name:'david'
}
var b = a
実際にはaとbはメモリ内の変数を指しているポインタを保存しています.bに対する修正は、aも同時に変化します.
b.name = 'jimmy'
console.log(a.name)//'jimmy'
同じように、Javascriptの学生を困らせる例がもう一つあります.jsでは関数のパラメータが値によって伝達されることを知っている.次の例では
var value1 = "test"
var value2 = {
  name:'david'
}
function a(v1,v2){
    v1 = "change"
    v2.name = "jimmy"
}
a(value1,value2)
console.log(value1)//test
console.log(value2)//{name:"jimmy"}
aを実行した後、value 1は変化しませんでしたが、value 2のnameは変わりました.関数実行時には、まず変数v 1,v 2を関数内部に初期化するからです.value 1は基本タイプなので、直接数値をコピーしました.value 2では参照型の変数をコピーします.コピー操作は実際にポインタをコピーしています.したがって、内部のv 2に対する操作はメモリ内の変数に影響を及ぼします.したがって、外部関数のvalue 2が変化した.
最初の話に戻ります.和深コピーとは何かを見てみます.
浅いコピーは簡単なコピー参照です.(オブジェクトの割当操作さえも、浅いコピーと見なすことができる)
function copy(target){
    var obj = Array.isArray(target)?[]:{}
    for(let i in target){
        obj[i] = target[i]
    }
    return obj
}
var david = {
    name:'david',
    info:{
        birth:1993
    }
}
var david_copy = copy(david)
david_copy.info===david.info//true
(いくつかの例では、浅いコピーは対象の原型の方法を削除しますが、個人的には深くする必要はないと思います.原型を取り除く方法は浅いコピーの二つの実現方法だけです.プロジェクトのニーズを見て、どれを使うかを決められます.)
SE 6には、オブジェクトのマージのためにObject.assignがあり、ソースオブジェクトのすべてのエニュメレーション属性を対象オブジェクトにコピーします.内部実装は、実際には浅いコピーであり、ターゲットの原型を削除する方法である.
var david_copy = Object.assign({},david)
david_copy.info===david.info//true
深くコピーすればよく分かります.まったく新しい相手が生まれました.浅いコピーは1つのオブジェクトの属性だけをコピーし、深いコピーはすべての階層にコピーされます.
深度コピーの実現方法については大同小異ですが、ここでは二つの方法を提供します.
function deepCopy(target){
    return JSON.parse(JSON.stringify(target))
}
しかし、この方法には弊害があります.1.関数をコピーできません.2.プロトタイプの方法と属性をコピーできません.
function deepCopy(target){
    var isArrayOrObject = function(o){
        return Object.prototype.toString.call(o)=="[object Array]"||Object.prototype.toString.call(o)=="[object Object]"
    }
    if(!isArrayOrObject(target)){
        //            
        return target
    }
    var createObj = function(o){
        return Object.prototype.toString.call(o)=="[object Array]"?[]:{}
    }
    
    var obj = createObj(target)
    var copy = function(target,container){
        for(var i in target){
            if(isArrayOrObject(target[i])){
                container[i] = createObj(target[i])
                copy(target[i],container[i])
            }else{
                container[i] = target[i]
            }
        }
        return container
    }
    return copy(target,obj)
}
補足して、domの操作の中にも深いコピーと浅いコピーがあります.clone Nodeは、ノードをコピーするために使用され、パラメータtrueに入ると、そのサブ世代をコピーします(イベントをクリックするなど、javascript処理プログラムをコピーしません).パラメータを読み込まない、またはfalseではノード自体をコピーします.