jsを使っていると、Array.prototype.splice()
を使うことがそこそこあるのですが、
最近まで間違って使っていたため、この機会に書いてみようと思います。
Array.prototype.splice()
まず簡単にですが、Array.prototype.splice()
について説明します。
名前の通り、Array
をsplice
(配列の要素を取り除いて、つなぎ合わせる。)関数なのですが、
この説明だけだとイメージがわかない方もいらっしゃるかもしれませんので、簡単な例を書いておきます。
1 2 3 4 |
let array = ["サイ", "ヘビ", "フクロウ", "ゾウ"]; console.log(array); // ["サイ", "ヘビ", "フクロウ", "ゾウ"] array.splice(1, 2); console.log(array); // ["サイ", "ゾウ"] |
当然ですが、インデックスが1
番目の要素から順に2
個の要素を削除して、配列をつなぎ合わせますので、
サイとゾウだけが配列に残ります。
すごく雑な説明なので正確に知りたい方は、ググってみてください。
次にいろんな動物が含まれる配列から、十二支に含まれない動物を削除していきたいと思います。
1 2 3 4 5 6 7 8 9 10 |
let animals = ["ねずみ", "うし", "とら", "う", "たつ", "み", "うま", "ひつじ", "さる", "とり", "いぬ", "いのしし", "イタチ", "ねこ"]; const excludeAnimals = ["イタチ", "ねこ"]; for (let index = 0; index < animals.length; index++) { if (excludeAnimals.includes(animals[index])) { // 十二支に含まれない動物を削除 animals.splice(index, 1); } } console.log(animals); // ["ねずみ", "うし", "とら", "う", "たつ", "み", "うま", "ひつじ", "さる", "とり", "いぬ", "いのしし", "ねこ"] |
本来ならイタチとねこは、十二支に含まれませんが、ねこが結果に含まれてしまっていることがわかるかと思います。
簡単にですが、ループ文をトレースした結果は以下のようになります。
index | animals[index] | animals.length |
0 | ねずみ | 14 |
1 | うし | 14 |
・ | ・ | 14 |
・ | ・ | 14 |
・ | ・ | 14 |
12 | イタチ | 14 |
13 | – | 13 |
※ animals.length
は3行目時点での値です。
index
が12の時に、splice
関数を実行した結果、animals.length
が14 => 13に変更されます。
また、 index
が13の場合、index < animals.length
⇔ 13 < 13
⇔ false
と評価され、
正しくループ処理ができないことをわかっていただけるかと思います。
※ ねこのインデックスも13
でなくなります。
対応策は簡単で、こんな感じに置き換えてもらえば、正しく動作することができます。
1 2 3 4 5 6 7 8 |
let animals = ["ねずみ", "うし", "とら", "う", "たつ", "み", "うま", "ひつじ", "さる", "とり", "いぬ", "いのしし", "イタチ", "ねこ"]; const excludeAnimals = ["イタチ", "ねこ"]; for (let index = animals.length - 1; index > -1; index--) { if (excludeAnimals.includes(animals[index])) { // 十二支に含まれない動物を削除 animals.splice(index, 1); } } |
以上。