JavaScript向div循环添加100个按钮仅生成1个的原因
DOM节点是引用类型的对象,同一个节点实例在整个DOM树中同一时间只能有一个挂载位置,appendChild 方法传入已存在的节点时,不会复制节点,只会执行「移动」操作:先把节点从原有父节点下移除,再插入到当前目标父节点的指定位置。
为什么第一种写法只生成1个按钮
你在循环外部仅调用了一次document.createElement('button'),全程只创建了1个button节点实例。
循环执行的100次appendChild(btn),本质是反复把这同一个按钮从div的原有位置挪到div子节点的末尾,并不是新增按钮,所以最终页面上只会保留1个按钮。
对应代码:
const btn = document.createElement('button'); const div = document.querySelector('div'); btn.innerText = 'Hey!'; for (let i = 0; i < 100; i++) { div.appendChild(btn); }
为什么第二种写法能生成100个按钮
你把节点创建逻辑放到了循环内部,每一轮循环都会调用一次document.createElement('button'),生成100个互相独立的全新button实例。
每次appendChild插入的都是之前没有挂载到DOM树上的新节点,不存在移动已有节点的逻辑,所以最终会成功渲染100个按钮。
对应代码:
for (let i = 0; i < 100; i++) { const btn = document.createElement('button'); const div = document.querySelector('div'); btn.innerText = 'Hey!'; div.appendChild(btn); }
可优化点
第二种写法里的const div = document.querySelector('div')属于可以提取到循环外的逻辑——DOM查询是有性能开销的,div节点本身全程不会变化,不需要每轮循环都重新查询,优化后写法更高效:
const div = document.querySelector('div'); for (let i = 0; i < 100; i++) { const btn = document.createElement('button'); btn.innerText = 'Hey!'; div.appendChild(btn); }
如果你确实想复用循环外创建的按钮节点,也可以在插入时调用节点克隆方法:
div.appendChild(btn.cloneNode(true)),传入true会深克隆节点的所有属性和子内容,这种方式也能生成100个按钮,但常规场景下直接在循环内创建新节点的可读性更好。
内容的提问来源于stack exchange,提问作者RandAlThor9561

