A .optionscoleção é (infelizmente) ativa , portanto, a iteração dos itens da coleção ao vivo um por um e .removecada um resultará na manutenção de todos os itens ímpares. (Por exemplo, certo quando você remove o primeiro item, o [0]item de th da coleção se tornará imediatamente o próximo item na coleção - que costumava ser [1]passará a ser [0](e, em seguida, uma vez que você vá para o próximo índice no [1], o novo item em posição 0 não será repetido)
Use em document.querySelectorAllvez disso, que retorna uma coleção que é estática:
for (const option of document.querySelectorAll('#form-select > option')) {
option.remove();
}
<select id="form-select">
<option>111</option>
<option>222</option>
<option>333</option>
</select>
Você também pode se espalhar para uma matriz (estática) antes de remover os elementos:
for (const option of [...document.querySelector('#form-select').options]) {
option.remove();
}
<select id="form-select">
<option>111</option>
<option>222</option>
<option>333</option>
</select>
Outra opção, que só acontece ao trabalho porque a coleção é ao vivo (mas provavelmente não deve ser utilizado, uma vez que não é intuitivo):
const { options } = document.querySelector('#form-select');
while (options.length) {
options[0].remove();
}
<select id="form-select">
<option>111</option>
<option>222</option>
<option>333</option>
</select>
.optionsé um array, que é a fonte do problema - é um HTMLCollection, que está ativo. Se fosse uma matriz, seria estática e não haveria problemas.