siguiente es el código que escribí. Si cambio el código en el ciclo for a i<len-1, entonces funciona bien, excepto por el último enlace. Pero si lo mantengo como i<len, no funciona para ningún enlace.
const allLists = document.querySelectorAll("a:link"); var len = allLists.length; for (var i = 0; i < len; i++) { allLists[i].addEventListener("click", function (e) { e.preventDefault(); const href = allLists[i].getAttribute("href"); console.log(href); if (href == "#") { window.scrollTo({ top: 0, behavior: "smooth", }); } }); }Error: script.js:33 TypeError no capturado: no se pueden leer las propiedades de undefined (leyendo 'getAttribute') en HTMLAnchorElement.
Porque i variable por len después de tu bucle
Entonces, cada vez que se llame al evento click, el código a ejecutar siempre será:
const href = allLists[len].getAttribute("href"); Este problema es un problema de closure , puedes ver más aquí
El código revisado se verá así: (cambie var a let )
const allLists = document.querySelectorAll("a:link"); var len = allLists.length; for (let i = 0; i < len; i++) { allLists[i].addEventListener("click", function (e) { e.preventDefault(); const href = allLists[i].getAttribute("href"); console.log(href); if (href == "#") { window.scrollTo({ top: 0, behavior: "smooth", }); } }); } <a href="1">1</a> <a href="2">2</a> <a href="3">3</a> <a href="4">4</a>Como se indica en los documentos para desarrolladores de Mozilla, "querySelectorAll() se comporta de manera diferente a las bibliotecas DOM de JavaScript más comunes, lo que podría generar resultados inesperados".
Por lo tanto, sugeriría seguir los documentos y codificar un bucle 'forEach' en lugar de un bucle 'for'.