Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   getElementsByTagName область видимости? (https://javascript.ru/forum/events/49749-getelementsbytagname-oblast-vidimosti.html)

grafvonfabercastel 27.08.2014 11:46

getElementsByTagName область видимости?
 
добрый день!

прошу вашей помощи в связи с вот чем:

к хтмл странице с несколькими заголовками h1 цепляется внешний скрипт.
если в скрипте код 1, то показывается второй заголовок h1 (то есть все ок). если в скрипте код 2, то в консоли undefined. Если в скрипте код №3, то a содержит массив из заголовков h1(что тоже верно). объясните, пожалуйста, в какую сторону у меня кривые руки и почему getElementsByTagName ведет себя по-разному.

заранее большое спасибо!

код №1

window.onload=function(){
var a = document.getElementsByTagName ("h1") [1];
console.log(a);
}

код №2
var a = document.getElementsByTagName ("h1") [1];
console.log(a);

код №3
var a = document.getElementsByTagName ("h1");
console.log(a);

Aetae 27.08.2014 12:43

getElementsByTagName возвращает NodeList - живую коллекцию элементов, не массив.
Соответственно:
код 1: всё ок, вы получаете коллекцию элементов уже после загрузки страницы когда все они уже присутствуют, берёте второй по счёту и передаёте на вывод console.log. console.log выводит его.

код 2: вы получаете коллекцию элементов до загрузки страницы, потому на момент вызова пустую, берёте второй элемент пустой коллекции(поскольку его нет то undefined) и передаёте на вывод console.log. console.log выводит undefined.

код 3: вы получаете коллекцию элементов до загрузки страницы, потому на момент вызова пустую, и передаёте оную на вывод console.log. Тут кроется подвох. Передаётся коллекция в console.log ссылкой а не копией, и поскольку когда вы смотрите в консоль страница уже успела загрузиться - коллекция успевает к тому времени заполниться элементами загруженной страницы. Потому вы и видите в консоли её элементы.
На момент вызова же она также пуста как и в коде 2.
Чтобы это увидеть можно преобразовать код 3 к след. виду:
var a = Array.prototype.slice.call( document.getElementsByTagName ("h1") ); //преобразуем живой NodeList в статичный массив
console.log(a);


P.S. Лично мне не слишком нравится такой подход в реализации console.log - удобнее и логичнее было бы при выводе делать полные копии переданных объектов на момент передачи. Наверное такой поход приводил к излишним расходам памяти или просто противоречил стилю js. Так или иначе теперь уже ничего не попишешь, просто надо учитывать, что в консоли мы увидим самое последнее состояние объекта, а не промежуточное.

grafvonfabercastel 27.08.2014 13:04

большое спасибо за подробное разъяснение!)))


Часовой пояс GMT +3, время: 17:27.