変数をコピーするとき「=」を使いますが、配列の場合そうはいきません。
複製元の値を変更すると、複製先まで連動して変わってしまいます。
そこで、戻り値に配列を返してくれるメソッド、concat、slice、fromなどを使ってコピーします。
目次(リンク)
代入演算子「=」ではコピーにならない
変数に値や他の変数を代入するとき、「=」を使いますよね。
値なら、
i = 1;
変数を代入するなら、
i = intMaxRow;
のような感じ。
でも配列の場合は違います。
最初の頃は同じようにやってしまいがちですが、実はこれでは配列を複製することができません。
試しにやってみましょう。
配列に値を代入した後、「=」で他の配列に入れようとします。
ちゃんと複製できていれば、元の配列の値を変更しても、事前にコピーしていた別の配列に影響ないはず。
でも実際には影響していて、コピーしておいたはずの配列まで値が変わっちゃうんです。
1 2 3 4 |
var list_array = ['a1','a2','a3']; var list_array2 = list_array; list_array[0] = 'b1' console.log(list_array2); //['b1','a2','a3']; |
「=」だと、値が格納されているメモリの参照をコピーしただけ。
同じところを見に行っていては、配列の複製にはなりません。
でも解決策はいくつかあります。
配列をコピーするには
concat、slice、fromなどのメソッドを使います。
concat()でコピーする
まずは、concat()メソッドを使うやり方から。
もともと配列を連結するとき使うメソッドです。
array1とarray2を結合した結果をarray3に代入するなら、次のように書きます。
1 |
array3 = array1.concat(array2); |
コピーするには、concatの引数を空にするだけ。
1 2 3 4 |
var list_array = ['a1','a2','a3']; var list_array2 = list_array.concat(); list_array[0] = 'b1' console.log(list_array2); //['a1','a2','a3']; |
コピーしてから値を代入しても、元の配列には影響ありません。
slice()でコピーする
配列の要素一部分を配列として返すのがsliceメソッドです。
1 2 3 |
var list_array = ['a1','a2','a3']; console.log(list_array[0]); //'a1' console.log(list_array.slice(1)); //['a2','a3'] |
引数が1なら、0番目の次の1番目から最後まで、配列で返ってきます。
配列をコピーするには、引数を空にするだけです。
0番目から最後まで、配列として戻り値が返ってきます。
1 2 3 4 |
var list_array = ['a1','a2','a3']; var list_array2 = list_array.slice();; list_array[0] = 'b1' console.log(list_array2); //['a1','a2','a3']; |
from()でコピーする
fromメソッドでコピーすることも出来ます。
1 2 3 4 |
var list_array = ['a1','a2','a3']; var list_array2 = Array.from(list_array); list_array[0] = 'b1' console.log(list_array2); //['a1','a2','a3']; |
上記のように基本的な配列の場合は問題なく使えます。
しかし、次のように参照型の場合、そうはいきません。
複製元の0番目のpriceを変更したのに、複製先まで影響してしまいました。
1 2 3 4 |
var arr_order = [{drink: 'soy latte', price: 470}, {drink: 'caffe mocha', price: 500}]; var arr_order2 = Array.from(arr_order); arr_order[0].price = 400; console.log(arr_order2); //[{drink: 'soy latte', price: 400}, {drink: 'caffe mocha', price: 500}]; |
concatやsliceメソッドでやろうとしても、fromメソッドと同じことになってしまいます。
参照型の配列の扱いには注意が必要ですね。
まとめ:配列をコピーする
代入演算子「=」では、参照をコピーするだけ、配列の複製はできません。
concat、slice、fromメソッドなどを利用すれば大丈夫!という内容でした。
ただ、これらのメソッドを使っても、参照型の配列の場合には注意してくださいね。