getElementsByTagName返回具有空元素的数组

时间:2020-01-02 22:11:31

标签: html dom tampermonkey

我有这个Tampermonkey脚本:

// ==UserScript==
// @name         Remove strong tags
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  remove answers
// @author       You
// @match        http://*/*
// @grant        GM_log
// @run-at       document-end
// ==/UserScript==

setTimeout((function() {
    'use strict';

    var allStrong = document.getElementsByTagName("strong");
    GM_log(allStrong);

    for (var i=0, max=allStrong.length; i < max; i++) {
        var strong = allStrong.item(i);
        GM_log(strong);
        if(strong && strong.parentNode.tagName == "LI") {
            strong.parentNode.appendChild(strong.firstChild);
            strong.parentNode.removeChild(strong);
        }
    }
})(), 5000);

在符合条件的8个strong标签中,它仅替换了4个。

这是在Chrome控制台中打印的。

enter image description here

第一次打印时,数组有8个元素,但最后4个元素被打印为undefined

为什么会这样?

我认为问题不在于加载整个页面之前执行的代码,因为我设置了很大的超时时间。

This是我运行它的页面。

2 个答案:

答案 0 :(得分:3)

getElementsByTagName返回所谓的实时Array,而不是静态的<strong>-这意味着它包含查询的最新结果。

因此,在每次迭代之后,都会删除其中一个元素,因为它不再是NodeList元素。

您在这里有2个选择:

  • Array转换为普通NodeList(例如,使用Array.from
  • 始终访问{{1}}的第一个元素

答案 1 :(得分:2)

第一个打印输出显示8个元素,因为它就是那时的内容。但这是一个 HTMLCollection ,并且在HTML DOM中是实时的。更改基础文档后,它会自动更新。

for循环会逐步删除其中的某些strong.parentNode.removeChild(strong);节点(max=allStrong.length),但只会在开始时计算集合的长度(setTimeout)。因此它仍然可以运行8次,但是到一半时,它不会进行任何迭代。

扩展日志的第一行时,Chrome浏览器会评估您的实时HTMLCollection,该HTMLHTMLCollection当时仅包含4个元素,因此仅显示4个元素。行告诉您何时对该表达式求值。

如果您想实时查看所有这些内容,而不是将其放在debugger; 中,则建议您在代码中添加以下语句,无论您想逐步查看它步骤:

NodeList