jsを使っていると、Array.prototype.splice()
を使うことがそこそこあるのですが、
最近まで間違って使っていたため、この機会に書いてみようと思います。
Array.prototype.splice()
まず簡単にですが、Array.prototype.splice()
について説明します。
名前の通り、Array
をsplice
(配列の要素を取り除いて、つなぎ合わせる。)関数なのですが、
この説明だけだとイメージがわかない方もいらっしゃるかもしれませんので、簡単な例を書いておきます。
let array = ["サイ", "ヘビ", "フクロウ", "ゾウ"];
console.log(array); // ["サイ", "ヘビ", "フクロウ", "ゾウ"]
array.splice(1, 2);
console.log(array); // ["サイ", "ゾウ"]
当然ですが、インデックスが1
番目の要素から順に2
個の要素を削除して、配列をつなぎ合わせますので、
サイとゾウだけが配列に残ります。
すごく雑な説明なので正確に知りたい方は、ググってみてください。
次にいろんな動物が含まれる配列から、十二支に含まれない動物を削除していきたいと思います。
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`でなくなります。
対応策は簡単で、こんな感じに置き換えてもらえば、正しく動作することができます。
let animals = ["ねずみ", "うし", "とら", "う", "たつ", "み", "うま", "ひつじ", "さる", "とり", "いぬ", "いのしし", "イタチ", "ねこ"];
const excludeAnimals = ["イタチ", "ねこ"];
for (let index = animals.length - 1; index > -1; index--) {
if (excludeAnimals.includes(animals[index])) {
// 十二支に含まれない動物を削除
animals.splice(index, 1);
}
}
以上。