JavaScript返回数组长度为0,但控制台中显示正确的长度

4

我有一个包含以下代码块的HTML页面。我无法更改它。 在JavaScript中,我想要找到所有类名为“language-link”的a元素,并获取它们的hreflang属性,所以我做了这个。

var lang_links = document.getElementsByClassName('language-link');
for (var i = 0; i < lang_links.length; i++) {
    console.log(lang_links[i].getAttribute('hreflang'));
}

但是出于某种原因,它没有打印任何东西。我发现lang_links.length等于0。如果我在for循环之前添加两个console.log,则如下所示,

var lang_links = document.getElementsByClassName('language-link');

console.log(lang_links);
console.log("length: " + lang_links.length);

for (var i = 0; i < lang_links.length; i++) {
    console.log(lang_links[i].getAttribute('hreflang'));
}
<nav class="links nav links-inline">
  <span hreflang="en" class="en nav-link is-active">
    <a href="/drupal/en" class="language-link is-active" hreflang="en">English</a>
  </span>
  <span hreflang="fr" class="fr nav-link">
    <a href="/drupal/fr" class="language-link" hreflang="fr">French</a>
  </span>
  <span hreflang="ar" class="ar nav-link">
    <a href="/drupal/ar" class="language-link" hreflang="ar">Arabic</a>
  </span>
</nav>

我的浏览器控制台输出

HTMLCollection []
> 0: a.language-link.is-active
> 1: a.language-link
> 2: a.language-link
  length: 3
> __proto__: HTMLCollection

length: 0

数组正确打印,并告诉我正确的长度,但当我打印数组的长度时,它显示为0,为什么?

此外,如果我在浏览器控制台中运行我的代码,我会得到预期的输出,其中显示了所有hreflang属性:

HTMLCollection(3) [a.language-link.is-active, a.language-link, a.language-link]
> 0: a.language-link.is-active
> 1: a.language-link
> 2: a.language-link
  length: 3
> __proto__: HTMLCollection

length: 3

en
fr
ar

可能是由于JavaScript代码在元素创建之前运行导致的吗?但如果是这种情况,console.log(lang_links) 就不应该打印任何内容...
编辑:我正在使用Drupal 8,因此无法更改HTML文档中脚本的位置(我想)。如果使用检查器,我看不到我的JavaScript文件,但看起来Drupal在body的末尾运行脚本,因为这里是检查器中所有脚本出现的地方,而且我的其他 getElementByClassName() 运行没有问题。

1
你是否在文档加载前在头部加载了 JS? - Drag13
1
lang_links 是一个对象,控制台显示对象的修改输出。您可以在 console.log(lang_links) 后添加调试器语句来验证这一点。当调试器暂停执行时,它会在控制台上打印 undefined。 - vcode
1个回答

1
大多数情况下,你的JS代码在DOM加载之前运行(或者如果是动态构建,则在构建完成之前),因为代码本身可以与静态内容良好地配合使用。
请检查你加载脚本的位置。如果它在head或body开头,请将其移到底部。这样做有双重好处,稍微提高了页面性能。
关于第二个问题,为什么会在控制台上显示,@vcode已经回答了。DOM元素是对象,你看到的是它们的“最终结果”。

如果我使用检查器,我看不到我的文件,但是看起来Drupal在body的末尾运行脚本,因为这是检查器中所有脚本出现的位置,并且我的其他getElementByClassName()调用没有问题。 - Chris Rahmé
你是否使用某个框架/代码来动态创建节点?请打开渲染后的HTML,并检查<script></script>标签与你的代码放置在哪里? - Drag13
是的,我正在使用Drupal。脚本标签放置在body的末尾。 - Chris Rahmé
1
我不熟悉Drupal,但是如果它在运行时动态呈现一些标记,则可能是原因。我建议使用简单的代码进行测试setTimeout(() => { if (!!document.querySelector('.language-link')) { console.log('I was created dynamically') } else {console.log('you missed')}}, 10000)并在代码库中快速搜索使用language-link类。也许你会发现它是如何添加的。 - Drag13
1
原来它们是动态创建的。但为什么其他所有东西都能正常工作呢?无论如何,非常感谢! - Chris Rahmé

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接