Удаление параметров из тега Select в Vanilla JavaScript с помощью цикла «for .. of»

10

При попытке удалить опции из select всегда остается один, почему?

<select id="form-select">   
<option>111</option>
<option>222</option>
<option>333</option>
</select>

Этот JS не работает:

var t = document.querySelector('#form-select'); 
for(var i of t.options) {
      t.remove(i.index)
    }

И это не работает также:

for(var i of document.querySelector('#form-select').options) {
  i.remove()
}

Я знаю, что есть другие решения для достижения этой цели, но я хотел бы понять, почему это не работает так, как должно

Петр
источник

Ответы:

7

.optionsКоллекция (к сожалению) в прямом эфире , так что итерация элементы живой коллекции в один-на-один и .removeИНГ каждый приведет к каждой нечетной держится. (Например, право , когда вы удалите первый элемент, то [0]й элемент коллекции сразу становится следующий элемент в коллекции - что раньше [1]станет [0](а затем , как только вы переходите к следующему индексу в [1], тем новый пункт в положении 0 не будет повторяться)

Используйте document.querySelectorAllвместо этого, который возвращает коллекцию, которая является статической:

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>

Вы также можете распространяться в (статический) массив перед удалением элементов:

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>

Другой вариант , который как раз случается к работе , потому что коллекция живой (но , вероятно , не следует использовать, так как это не интуитивно):

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>

CertainPerformance
источник
3

Вы удаляете элементы из массива, когда выполняете итерацию по массиву. Так что у тебя есть:

["one","two","three"]

затем вы удаляете элемент с индексом 0, который равен «единице», оставляя вас с:

["two","three"]

затем вы удаляете элемент с индексом 1, который равен «трем», оставляя вас с:

["two"]

нет элемента с индексом 2, поэтому цикл останавливается.

Вместо этого перебираем массив в обратном порядке :

const t = document.querySelector("#form-select")

for (let i = t.options.length-1; i >= 0; i--) {
  t.removeChild(t.options[i])
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>

символическая
источник
.optionsЭто не массив, который является источником проблемы - скорее, что это HTMLCollection, который находится под напряжением. Если бы это был массив, он был бы статичным, и не было бы никаких проблем.
CertainPerformance
1
@CertainPerformance удаления элементов из массива , как вы итерация это делает причину этой проблемы я проиллюстрированная.
символическая ссылка
1
@CertainPerformance HTMLOptionsCollectionОбъект действует в этом контексте как массив.
символическая ссылка
2

Я вижу, что ваша главная цель - понять процесс, который вызывает это, поэтому это должно проиллюстрировать проблему для вас:

var arr = ["one", "two", "three", "four", "five", "six"];

for(var i = 0; i < arr.length; i++){
	console.log("i is " + i + ", so we are removing \"" + arr[i] + "\" from " + JSON.stringify(arr) + ".");
	arr.splice(i, 1);
	console.log("After that removal, the array is " + JSON.stringify(arr) + ". We'll now iterate i to " + (i + 1) + " and continue the loop.");
}
console.log("i is too high to grab a value from the array, so we're finished. We're left with " + JSON.stringify(arr) + ".");

Этот цикл проходит точно такой же тип процесса, что и ваш цикл "for .. of", чтобы оставить вас с дополнениями в конечном результате. Проблема состоит в том, что он разрушает свои собственные индексы при их итерации, тем самым изменяя значение, на iкоторое действительно ссылаются. Когда я сталкиваюсь с этой проблемой, мне нравится перебирать массив задом наперед, чтобы на меня не повлияло мое собственное уничтожение, например:

var arr = ["one", "two", "three", "four", "five", "six"];

for(var i = arr.length - 1; i >= 0; i--){
	console.log("i is " + i + ", so we are removing \"" + arr[i] + "\" from " + JSON.stringify(arr) + ".");
	arr.splice(i, 1);
	console.log("After that removal, the array is " + JSON.stringify(arr) + ". We'll now iterate i to " + (i - 1) + " and continue the loop.");
}
console.log("i is too low to grab a value from the array, so we're finished. We're left with " + JSON.stringify(arr) + ".");

Я надеюсь, что это поможет вам полностью понять, что здесь происходит. Если у вас есть какие-либо вопросы, не стесняйтесь оставить мне комментарий.

Аарон Плочарчик
источник
0

Вы перебираете тот же массив, где изменяется индекс после удаления элемента из массива. Ниже приведен пример, где вы можете перебирать опции без индекса и удалять его из массива.

var selectOptions = document.querySelectorAll('#remove-option>option');
selectOptions.forEach(function(selectOption) {
  selectOption.remove();
  selectOption = null;
});

Вот скрипка

kichus14
источник