使用“ for..of”循环从Vanilla JavaScript中的Select标签中删除选项


10

当试图从选择中删除选项时,总是剩下一个,为什么?

<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()
}

我知道还有其他解决方案可以实现这一目标,但是我想了解为什么它无法正常运行

Answers:


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>


3

你从一个数组删除项目,您通过数组迭代。所以你有了:

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

然后您删除索引为0(即“ 1”)的项,则留给您:

["two","three"]

接下来,您删除索引1处的项目“ 3”,剩下的就是:

["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,其为活的。如果是数组,它将是静态的,并且不会有任何问题。
某些性能

1
@CertainPerformance在您遍历数组时从数组中删除元素确实会引起我所说明的问题。
symlink

1
@CertainPerformance HTMLOptionsCollection在这种情况下,对象的行为就像一个数组。
symlink

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;
});

这是小提琴

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.