state を扱っていると配列の操作をする機会が多いのですが配列から値を取り出す時の slice
と splice
似てる。
Array.prototype.slice
arr.slice([begin[, end]])
slice
は取り出す位置 (begin
) から終了位置 (end
) までの要素を取り出す。
戻り値は取り出された値の配列。
終了位置の要素は含まれず、end
が省略さた場合は、begin
から配列の最後 (length
) までが指定される。
配列は shallow コピーされるので元の配列は変更されない。
e.g.
const arr = ['星宮いちご', '霧矢あおい', '紫吹蘭', '大空あかり', '氷上すみれ', '新条ひなき']; const akari = arr.slice(3, 4); // => ['大空あかり'] const luminas = arr.slice(3); // => ['大空あかり', '氷上すみれ', '新条ひなき'] // 新しい配列が返されるので元の配列に変化はなし console.log(arr); // => ['星宮いちご', '霧矢あおい', '紫吹蘭', '大空あかり', '氷上すみれ', '新条ひなき'] // 引数なしで配列のコピーができる const clone = arr.slice(); clone.reverse().push('神崎美月'); console.log(clone); // => ['新条ひなき', '氷上すみれ', '大空あかり', '紫吹蘭', '霧矢あおい', '星宮いちご', '神崎美月'] console.log(arr); // => ['星宮いちご', '霧矢あおい', '紫吹蘭', '大空あかり', '氷上すみれ', '新条ひなき']
shallow copy なので object などの参照になってる値には注意が必要
const arr = [ { name: '星宮いちご', type: 'cute' }, { name: '霧矢あおい', type: 'cool' }, { name: '紫吹蘭', type: 'sexy' }, { name: '有栖川おとめ', type: 'pop' }, ]; // 配列をコピー const copy = arr.slice(); // コピーした配列の操作やインデックスの値を丸っと置き換えるのは問題ない copy.pop(); copy[2] = { '新条ひなき', type: 'pop' }; console.log(copy); /* [ {name: "星宮いちご", type: "cute"}, {name: "霧矢あおい", type: "cool"}, {name: "新条ひなき", type: "pop"}, ] */ console.log(arr); /* [ {name: "星宮いちご", type: "cute"}, {name: "霧矢あおい", type: "cool"}, {name: "紫吹蘭", type: "sexy"}, {name: "有栖川おとめ", type: "pop"}, ] */ // 配列内のオブジェクトは参照のままなので変更すると元の配列の値に影響がある copy[0].name = '大空あかり'; copy[1].name = '氷上すみれ'; console.log(copy); /* [ {name: "大空あかり", type: "cute"}, {name: "新条ひなき", type: "cool"}, {name: "新条ひなき", type: "pop"}, ] */ console.log(arr); /* [ {name: "大空あかり", type: "cute"}, {name: "氷上すみれ", type: "cool"}, {name: "紫吹蘭", type: "sexy"}, {name: "有栖川おとめ", type: "pop"}, ] */
Array.prototype.splice
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
splice
は開始位置 (start
)と取り出す個数 (deleteCount)
を指定して配列から要素を削除して取り出す。
戻り値は取り出された値の配列で、取り出された値は元の配列から削除される。(破壊的変更)
const arr = ['星宮いちご', '霧矢あおい', '紫吹蘭', '大空あかり', '氷上すみれ', '新条ひなき']; const luminas = arr.splice(3, 3); console.log(luminas); // => ["大空あかり", "氷上すみれ", "新条ひなき"] // 元の配列も変更される console.log(arr); // => ["星宮いちご", "霧矢あおい", "紫吹蘭"] // 第2引数以降に値を渡すと取り出した位置に値を追加できる const soleil = arr.splice(0,2, '神崎美月', '藤堂ユリカ'); console.log(soleil); // => ["星宮いちご", "霧矢あおい"] console.log(arr); // => ["神崎美月", "藤堂ユリカ", "紫吹蘭"]
所感
配列な state を変更する際に、元の state を変更せずに要素を取り出すには slice
、値を取り出した残りの配列を使いたい場合は splice
を使うのが良さそう。
splice
を使う場合も [...state].splice
として元の配列をコピーして操作するのが immutable な感じで良いかなーと思います。
それにしても何で slice
は終了位置で、 splice
は要素数なんだろう。紛らわしくない?
[参考]

- 作者:狩野 祐東
- 発売日: 2019/09/21
- メディア: 単行本
![【Amazon.co.jp限定】アイカツオンパレード! Blu-ray BOX 2 (描き下ろしB2布ポスター[姫石らき]付) 【Amazon.co.jp限定】アイカツオンパレード! Blu-ray BOX 2 (描き下ろしB2布ポスター[姫石らき]付)](https://m.media-amazon.com/images/I/61+Z+8PpI4L._SL160_.jpg)
【Amazon.co.jp限定】アイカツオンパレード! Blu-ray BOX 2 (描き下ろしB2布ポスター[姫石らき]付)
- 発売日: 2020/08/05
- メディア: Blu-ray