JavaScript:DOM添加元素时元素对象为何被“消耗”?
关于DOM元素重复添加的两个问题
我有4个下拉菜单:fs2_beginn、fs3_beginn、fs2_ende和fs3_ende,需要为它们填充文本与值均为5到10的<option>元素。我写了一段在onload时执行的嵌套循环代码可以完成任务:
for(let j=2;j<=3;j++) { let fsDropdown1 = document.getElementById('fs'+j+'_beginn'); let fsDropdown2 = document.getElementById('fs'+j+'_ende'); for( let i = 5; i <=10; i++){ fsDropdown1.add(new Option(i,i)); fsDropdown2.add(new Option(i,i)); } }
问题1:为什么复用同一个Option实例时只有第二次add生效?
如果把代码改成先定义let x=new Option(i,i);,再两次调用add(x),结果只有第二次add操作生效:
// 仅示例问题代码片段 for( let i = 5; i <=10; i++){ let x = new Option(i,i); fsDropdown1.add(x); fsDropdown2.add(x); // 只有这次生效 }
问题2:为什么必须重新创建option元素才能添加到第二个下拉?
如果用createElement创建option,代码如下时可以正常工作,但如果删掉第1-3行(重新创建option的代码),就只有第一次add生效:
// 仅示例问题代码片段 for( let i = 5; i <=10; i++){ let fsOption = document.createElement('option'); fsOption.text = i; fsOption.value = i; fsDropdown1.add(fsOption); fsOption = document.createElement('option');// Line 1 fsOption.text = i; // Line 2 fsOption.value = i; // Line 3 fsDropdown2.add(fsOption); }
为什么DOM添加操作会“消耗”元素对象?(使用appendChild时也会出现相同行为;尝试过let、var和const的多种组合,均无影响。)
解答
这两个问题本质是同一个DOM规则导致的:
- DOM节点是唯一的,一个节点只能属于一个父元素。每个DOM元素对象(比如这里的
<option>)在DOM树中只能有一个父节点。 - 当你尝试把同一个节点添加到第二个父元素时,浏览器不会复制这个节点,而是执行移动操作:把节点从原来的父元素中移除,再添加到新的父元素里。
对应到你的问题:
- 复用同一个
x = new Option(i,i)时,第一次add把它加到fsDropdown1,第二次add会把它从fsDropdown1里移走,加到fsDropdown2,所以最后只有第二个下拉里有这个option。 - 不重新创建
fsOption时,第一次add后它已经是fsDropdown1的子节点,第二次add会把它移动到fsDropdown2,导致fsDropdown1里的这个option消失,看起来只有第一次add“没生效”。
如果想要复制节点,可以使用element.cloneNode(true)方法,比如:
let x = new Option(i,i); fsDropdown1.add(x); fsDropdown2.add(x.cloneNode(true)); // 复制节点后添加
内容的提问来源于stack exchange,提问作者Sascha
相关产品推荐
相关产品推荐

