はじめに
javaScriptでの配列のコピーのしかたについてまとめましたφ(・ω・ )
理由は自分が多次元配列をコピーしようとしたときに、どうしても参照渡しになってしまったからです(´+ω+`)
「配列 コピー」で調べても、多次元配列のコピーについて言及されているものが出てこなかったので、
「配列 コピー」で調べた人も多次元配列のコピーの方法にたどり着けるように、ここにまとめましたφ(・ω・ )
目次
- 参照渡し
- 値渡し
- 多次元配列の値渡し
- まとめ
1.参照渡し
例えば下記のように配列をコピーするとφ(・ω・ )
const listA = [1,2,3]
const listB = listA
console.log(listA) //[1, 2, 3]
console.log(listB) //[1, 2, 3]
下記を追記するとφ(・ω・ )
listB[0] = 80
console.log(listA) //[80, 2, 3]
console.log(listB) //[80, 2, 3]
このようにlistBの値を変更しただけなのに、listAの中身も変更されてしまいます。
これはlistBがlistAと同じところを参照しているからです_φ(..)
2.値渡し
配列の値渡しのパターンはいろいろあるようですが、
ここでは4パターン紹介しますφ(・ω・ )
slice
const listA = [1,2,3]
const listB = listA.slice()
console.log(listA) //[1, 2, 3]
console.log(listB) //[1, 2, 3]
下記を追記するとφ(・ω・ )
listB[0] = 80
console.log(listA) //[1, 2, 3]
console.log(listB) //[80, 2, 3]
これなら参照渡しにならず、新たな配列として値を渡せますφ(・ω・ )
concat
const listA = [1,2,3]
const listB = listA.concat()
console.log(listA) //[1, 2, 3]
console.log(listB) //[1, 2, 3]
下記を追記するとφ(・ω・ )
listB[0] = 80
console.log(listA) //[1, 2, 3]
console.log(listB) //[80, 2, 3]
先ほどのsliceと同じ結果が得られますφ(・ω・ )
concatは配列と配列をくっつけるメソッドなので、
引数に何か配列が入っていたら配列と配列ががっしゃんこして出てきますφ(・ω・ )
const listC = listA.concat(listB)
console.log(listC) //[1, 2, 3, 80, 2, 3]
Array.from
const listA = [1,2,3]
const listB = Array.from(listA)
console.log(listA) //[1, 2, 3]
console.log(listB) //[1, 2, 3]
下記を追記するとφ(・ω・ )
listB[0] = 80
console.log(listA) //[1, 2, 3]
console.log(listB) //[80, 2, 3]
sliceのときと結果は同じですねφ(・ω・ )
スプレッド構文
const listA = [1,2,3]
const listB = [...listA]
console.log(listA) //[1, 2, 3]
console.log(listB) //[1, 2, 3]
下記を追記するとφ(・ω・ )
listB[0] = 80
console.log(listA) //[1, 2, 3]
console.log(listB) //[80, 2, 3]
これもsliceのときと結果は同じですφ(・ω・ )
3.多次元配列の値渡し
ここは引っかかりポイントです(´+ω+`)
まず下記をご覧ください(´+ω+`)
const listA = [[1,2,3],[1,2,3]]
const listB = listA.slice()
console.log(listA) //[[1,2,3],[1,2,3]]
console.log(listB) //[[1,2,3],[1,2,3]]
下記を追記するとφ(・ω・ )
listB[2] = 80
console.log(listA) //[[1,2,3],[1,2,3]]
console.log(listB) //[[1,2,3],[1,2,3],80]
さらに下記を追記するとφ(・ω・ )
listB[0][0] = 80
console.log(listA) //[[80,2,3],[1,2,3]]
console.log(listB) //[[80,2,3],[1,2,3],80]
このような結果になりますφ(・ω・ )
つまり、先ほどの4つのどのパターンで多次元配列を値渡ししようとしても、
ネストされた配列は参照渡しになってしまうのです(´+ω+`)
まいったまいった(´+ω+`)
JSON.parse(JSON.stringify())
ここで活躍するのがJSON.parseですφ(・ω・ )
const listA = [[1,2,3],[1,2,3]]
const listB = JSON.parse(JSON.stringify(listA))
// console.log(listA)
// console.log(listB)
さらに下記を追記するとφ(・ω・ )
listB[0][0] = 80
console.log(listA) //[[1,2,3],[1,2,3]]
console.log(listB) //[[80,2,3],[1,2,3]]
ちゃんと値渡しすることができました(`・∀・´)ノ!!
4.まとめ
コピーの結果が変わってくるのは参照するところが変わるからで、
これを浅いコピーと深いコピーの違いというそうですφ(・ω・ )
ここにはその辺りの詳細は書きませんので、気になる方は調べてみてくださいφ(・ω・ )
以上、javaScriptでの配列コピーのいろいろなやり方でした ε=ε=┏( ・_・)┛