配列やオブジェクトを操作することができるES6拡張オペレータに添加しました。時々遭遇コピー配列やオブジェクトは、拡張された演算子を使用する場合があります。そして、最終的にはこの拡張オペレータは、ディープコピーまたはそれの浅いコピーですか?
A.、拡張オペレータコピー
最初は、次のコードです。
せ= [1,2,3 ]。 聞かせてB = [... A];
== B //偽
結果は、すべての後に、知っていることは非常に簡単で、偽で、代入演算子は異なっています。次は何が起こるか、変更のちょうど配列となります。
せ= [1,2,3 ]。 聞かせてB = [... A]; [ 0] = 11 。 console.log(A)。// [11、2、3] にconsole.log(B)。// [1、2、3]
値が変更された後に発見されたBは変更されません。だから、ディープコピーはまだですか?心配しないで、配列の次の要素が参照型に設定されています。
= [1,2、[1,2,3ましょう]。 聞かせてB = [... A]; [ 2] [1] = 11 。 console.log(A)。// [1、2、[1、11、3] にconsole.log(B)。// [1、2、[1、11、3]
console.log([2] === B [2])。//真
アレイ型素子における基準値が変更された場合、この興味深い結果は、次いで、Bの値が変更され、基準タイプとB一致は、そのアドレスは同じです。なぜこれが?
二.、原因
これは、現在の知覚の唯一の私の最初の分析です。
拡張オペレータアレイのみ浅いコピー、コピーの最初の基準型層のデータのみ、およびNOコピーが実行されないならば、深いレベルです。
オペレータアレイの更なる拡張は、オブジェクトと同じです。
=を聞かせて{ :名 "JYY" 、 MSG:{ 年齢: 29 } } 聞かせてB = {...}; console.log( == B)。 // 偽 にconsole.log(a.msg == b.msg)。 // 真; a.msg = { 年齢: "28" } はconsole.log()。// {名: 'JYY'、MSG:{年齢: '28'}} にconsole.log(B)。// {名: 'JYY'、MSG:{年齢:29}}
第三に、深い浅いコピーのコピー方法
1.メソッドの浅いコピー
上記の例では、第一の層の種類を参照の単なるコピーES6拡張オペレータに見られました。拡張オペレータES6他の方法に加えて
オブジェクト:
使用Object.assign()
最初のパラメータがある場合に複合オブジェクトのObject.assignは()、{}は、コピーオブジェクトパラメータの背面にあってもよいです
=せ{ :名称 "JYY" 、 MSG:{ 年齢: 29 } } Bせ = Object.assign({})。 console.log( == B)。 // 偽 にconsole.log(a.msg == b.msg)。 // 真; a.msg = { 年齢: "28" } はconsole.log()。// {名: 'JYY'、MSG:{年齢: '28'}} にconsole.log(B)。// {名: 'JYY'、MSG:{年齢:29}}
アレイ:
配列の多くの方法の浅いコピー
A。スライスを使用して()
スライスは、配列要素の一部を遮ることができる引数がヌルである場合、配列は、浅いコピーすることができ
= [1,2、[1,2,3ましょう]。 せ、B = a.slice()。 console.log( == B)。 // 偽 A [2] [1] = 11 。 [ 0] = 11 。 console.log(A)。// [11、2、[1、11、3] にconsole.log(B)。// [1、2、[1、11、3] はconsole.log([2] == B [2])。 // 真
B。CONCATを使用して()
連結配列は、引数がnullの場合、配列は浅いコピーであってもよいし、マージすることができます
= [1,2、[1,2,3ましょう]。 せ、B = a.concat()。 console.log( == B)。 // 偽 A [2] [1] = 11 。 [ 0] = 11 。 console.log(A)。// [11、2、[1、11、3] にconsole.log(B)。// [1、2、[1、11、3] はconsole.log([2] == B [2])。 // 真
C。使用Array.from()
= [1,2、[1,2,3ましょう]。 Bせ = Array.from(A)。 console.log( == B)。 // 偽 A [2] [1] = 11 。 [ 0] = 11 。 console.log(A)。// [11、2、[1、11、3] にconsole.log(B)。// [1、2、[1、11、3] はconsole.log([2] == B [2])。 // 真
2.ディープコピー
ディープコピーについて、方法及びオブジェクトの配列が一致しています
。再帰法は、特定のコードが書き込まれていない、コピーするためのループの層を使用することです
b.JSON.parse()
この方法は、典型的には、コール・インターフェースまたはオブジェクトが順番に返される文字列のデータ伝送パラメータです。
=せ{ :名称 "JYY" 、 年齢 "25" 、 MSG:{ ADDR: "河北" } } 、B = JSON.parse(JSON.stringify())。 console.log( == B)。 // 偽 にconsole.log(a.msg == b.msg)。 // 偽 a.msg.addr =「承徳」。 console.log(A)。// {名: 'JYY'、年齢: '25'、MSG:{ADDR '承徳'}} にconsole.log(B)。// {名: 'JYY'、年齢: '25'、MSG:{ADDR: '河北'}}
この方法の欠点は、そのされundefined
、function
、symbol
変換プロセスでは無視され
=せ{ :名称 "JYY" 、 年齢 "25" 、 MSG:{ ADDR: "河北" }、 SPEEK:関数(){ にconsole.log(この.nameの)。 } } 、B = JSON.parse(JSON.stringify())。 console.log(A)。// {名: 'JYY'、高さ:シンボル(JYY)、年齢:不定、MSG:{ADDR '承徳'}、SPEEK:[機能:SPEEK]} にconsole.log(B)。// {名: 'JYY'、MSG:{ADDR '河北'}}
C。サードパーティ製プラグインを使用します
例lodash深いコピーのために
CONST _ =( "lodash"を必要とします)。 聞かせてSYB =記号( 'JYY' ); ましょう = { :名称 "JYY" 、 高さ:SYB、 年齢:不定、 MSG:{ ADDR: "河北" }、 SPEEK:関数(){ にconsole.log(この.nameの)。 } } Bせ = _。cloneDeep(A)。 console.log( == B)。 // 偽 にconsole.log(a.msg == b.msg)。 // 偽 にconsole.log(); //{名: 'JYY'、高さ:シンボル(JYY)、年齢:不定、MSG:{ADDR '承徳'}、SPEEK:[機能:SPEEK]} にconsole.log(B)。// {名: 'JYY'、高さ:シンボル(JYY)、年齢:不定、MSG:{ADDR '承徳'}、SPEEK:[機能:SPEEK]}