Мне было интересно, JavaScript предлагает множество методов для получения первого дочернего элемента из любого элемента, но какой из них лучший? Под лучшими я имею в виду: кросс-браузерную совместимость, быструю, наиболее полную и предсказуемую, когда дело доходит до поведения. Список методов / свойств, которые я использую как псевдонимы:
var elem = document.getElementById('container');
var child = elem.children[0];
var child = elem.firstElementChild; // == children[0]
Это работает для обоих случаев:
var child = elem.childNodes[0]; // or childNodes[1], see below
Это в случае форм или <div>
итерации. Если я могу встретить текстовые элементы:
var child = elem.childNodes; // treat as NodeList
var child = elem.firstChild;
Насколько я могу понять, firstChild
использует NodeList из childNodes
и firstElementChild
использует children
. Я основываю это предположение на ссылке MDN:
childNode
является ссылкой на первый дочерний элемент узла элемента или,null
если его нет.
Я предполагаю, что с точки зрения скорости, разница, если таковая имеется, будет почти нулевой, поскольку firstElementChild
фактически является ссылкой children[0]
на children
объект , и объект в любом случае уже находится в памяти.
Что бросает меня, это childNodes
объект. Я использовал его, чтобы взглянуть на форму, на элемент таблицы. Хотя children
перечисляет все элементы формы, childNodes
также, кажется, включает пробелы из кода HTML:
console.log(elem.childNodes[0]);
console.log(elem.firstChild);
Оба журнала <TextNode textContent="\n ">
console.log(elem.childNodes[1]);
console.log(elem.children[0]);
console.log(elem.firstElementChild);
Все бревно <input type="text"
... >
. Как придешь? Я бы понял, что один объект позволил бы мне работать с «сырым» HTML-кодом, в то время как другой придерживается DOM, но этот childNodes
элемент работает на обоих уровнях.
Возвращаясь к моему первоначальному вопросу, я могу предположить, что если я хочу получить наиболее полный объект, childNodes
это путь, но из-за его полноты он может быть не самым предсказуемым с точки зрения возврата элемента, который я хочу / ожидать в любой момент. Кросс-браузерная поддержка также может оказаться проблемой в этом случае, хотя я могу ошибаться.
Кто-нибудь может прояснить различие между предметами под рукой? Если есть разница в скорости, как бы она ни была незначительна, я бы тоже хотел знать. Если я вижу все это неправильно, не стесняйтесь обучать меня.
PS: Пожалуйста, пожалуйста, мне нравится JavaScript, так что да, я хочу иметь дело с такого рода вещами. Ответы типа «jQuery занимается этим для вас» - не то, что я ищу, поэтому нетJQuery тег.
источник
Ответы:
Звучит так, будто ты слишком много думаешь. Вы заметили разницу между
childNodes
иchildren
, которая заключается в том, что онаchildNodes
содержит все узлы, включая текстовые узлы, состоящие полностью из пробелов, в то времяchildren
как это коллекция только дочерних узлов, которые являются элементами. Это действительно все, что нужно сделать.В каждой коллекции нет ничего непредсказуемого, хотя следует учитывать несколько моментов:
childNodes
то время как другие браузеры делаютchildren
то время как другие браузеры имеют только элементыchildren
,firstElementChild
И друзья просто удобство, представляющее отфильтрованный вид DOM ограничивается только элементами.источник
<td\n\t>content</td>
. Как вы могли бы сделать с XML, чтобы избежать лишних пробелов, рассматриваемых как часть данных (или DOM, в данном случае). Почему пробелы внутри тега должны быть включены в DOM?children
появился в IE 4 более десяти лет, прежде чем стал стандартом или был принят другими браузерами, вы можете утверждать, что IE <= 8 является правильным, а другие браузеры - неправильными.firstElementChild может быть недоступен в IE <9 (только firstChild)
в IE <9 firstChild является firstElementChild, потому что MS DOM (IE <9) не хранит пустые текстовые узлы. Но если вы сделаете это в других браузерах, они вернут пустые текстовые узлы ...
мое решение
child=(elem.firstElementChild||elem.firstChild)
это даст первому ребенку даже на IE <9
источник
elem.firstChild
это не узел элемента, результаты в старых IE будут отличаться, потому чтоelem.firstElementChild
это всегда узел элемента.firstElementChild
также не обязательно безопасен в браузерах не IE: Firefox начал поддерживать его только в версии 3.5.Кросс-браузерный способ - использовать
childNodes
для полученияNodeList
, а затем создать массив всех узлов сnodeType
ELEMENT_NODE .http://jsfiddle.net/s4kxnahu/
Это особенно легко, если вы используете служебную библиотеку, такую как lodash :
Будущее:
Можно использовать
querySelectorAll
в сочетании с:scope
псевдо-класса (соответствует элементу , который является точкой отсчета селектора):На момент написания статьи это
:scope
поддерживается в Chrome, Firefox и Safari.источник
Просто чтобы добавить к другим ответам, здесь все еще есть заметные различия, особенно когда речь идет об
<svg>
элементах.Я использовал оба
.childNodes
и.children
и предпочел работать сHTMLCollection
доставлено в.children
поглотителе.Однако сегодня я столкнулся с проблемами сбоя IE / Edge при использовании
.children
на<svg>
. Хотя.children
поддерживается в IE для базовых элементов HTML, он не поддерживается для фрагментов документа / документа или элементов SVG .Для меня я был в состоянии просто захватить необходимые элементы через,
.childNodes[n]
потому что у меня нет посторонних текстовых узлов, чтобы беспокоиться. Вы можете сделать то же самое, но, как уже упоминалось выше, не забывайте, что вы можете столкнуться с неожиданными элементами.Надеюсь, что это полезно для того, чтобы кто-то почесал голову, пытаясь понять, почему он
.children
работает в других местах своих js на современном IE и не работает с элементами документа или SVG.источник
Эй, ребята, не позволяйте пустому пространству обмануть вас. просто проверьте это в консольном браузере. использовать родной JavaScript. Вот и пример с двумя наборами 'ul' с одним и тем же классом. Вам не нужно иметь список 'ul' в одной строке, чтобы избежать пробелов, просто используйте количество массивов, чтобы перепрыгнуть через пробелы.
Как обойти белое пространство ,
querySelector()
тоchildNodes[]
Js скрипки ссылки: https://jsfiddle.net/aparadise/56njekdo/источник
document.querySelector
его не поддержали. б) Вопрос, в основном, заключается в том, каковы различия между внутреннимchildren
иchildNodes
внутренним , что более надежно, когда выбирать одно из другого. и в) Потому что, как demonstraded в вопросе:childNodes
действительно включают пробельные узлы,children
не ...