Pull to refresh

Comments 17

Странно, что в интерфейс включили childElementCount. По-моему, было бы логичнее включить childElements, аналог childNodes, а у него уже можно и количество узнать.
Наверное, решили не дублировать уже имеющийся во всех браузерах, кроме Firefox, геттер children, пришедший из IE4, а для Firefox его можно сделать тем же __defineGetter__. Кстати, children появится в новой версии Firefox 3.5, об этом написано в MDC на странице «Firefox 3.5 for developers» в разделе «Other improvements».
а чем это отличается от обычной обертки? Т.е. node у нас будет обладать некоторыми свойствами, которые иногда будут использоваться (именно иногда, поэтому дополнительная нагрузка на дерево может превысить пользу от этого подхода).
Стандартные методы, геттеры и сеттеры тоже в прототипе находятся, не думаю, что добавление еще нескольких пользовательских геттеров в прототип объекта Element/HTMLElement для браузеров, не поддерживающих ElementTraversal, существенно понизит производительность, но все же попробую протестировать.
Тестировал на следующем коде:
var t1 = new Date().getTime(), i = 100000, doc = document;
while(i--) doc.createElement('div');
t1 = new Date().getTime() - t1;

if(window.HTMLElement) {
  HTMLElement.prototype.__defineGetter__("getter1", function(){});
  HTMLElement.prototype.__defineGetter__("getter2", function(){});
  HTMLElement.prototype.__defineGetter__("getter3", function(){});
  HTMLElement.prototype.__defineGetter__("getter4", function(){});
  HTMLElement.prototype.__defineGetter__("getter5", function(){});
}
else {
  Object.defineProperty(Element.prototype, "getter1", {get: function(){}});
  Object.defineProperty(Element.prototype, "getter2", {get: function(){}});
  Object.defineProperty(Element.prototype, "getter3", {get: function(){}});
  Object.defineProperty(Element.prototype, "getter4", {get: function(){}});
  Object.defineProperty(Element.prototype, "getter5", {get: function(){}});
}

i = 100000;

var t2 = new Date().getTime();
while(i--) doc.createElement('div');
t2 = new Date().getTime() - t2;

document.title = t1 + ' / ' + t2;
Разницы в скорости не заметил :-)
Ну вообще-то навигацию по DOM дереву лично мне больше нравиться делать через XPath выражения. Вполне наглядно и добно.

Игнорирование текстовых узлов созданых непечатными символами давно уже используется в IE. Я бы даже сказал, только так и используется )) В принципе хорошо, что и в других предусмотрели возможность работы согласно подобной схеме.
— если нода изначально «пуста», то полетят ошибки;
'children' лучше выкинуть (не-стандарт, есть баги);
— упростить бы 'do-if-break-while', заодно из консоли сгинут уорнинги;
— строго (===) сравнивать 'typeof' не обязательно…

>могу написать подробнее
Конечно, пиши.

+1
если нода изначально «пуста», то полетят ошибки
Спасибо, поправил.

'children' лучше выкинуть (не-стандарт, есть баги)
Не сталкивался с проблемами при использовании children, можно подробнее?

упростить бы 'do-if-break-while', заодно из консоли сгинут уорнинги
Вообще я за то, чтобы пользоваться всей гибкостью языка, но тоже поправил :-)

строго (===) сравнивать 'typeof' не обязательно
Так быстрее
>можно подробнее
IE видит комментарии, остальные гипотетически могут реализовать с ошибками, ибо нестандарт.

>Вообще я за то
Кто ж против, только break-ать надо ли? Если правильная нода сразу же нашлась, то просто не стоит заходить ни внутрь 'do-while', ни в 'while'. Алгоритм для всех случаев по идее один и тот же — в двух случаях идём налево, в двух — направо, но логика одна, не две, что и получилось сейчас.

>Так быстрее
Тест есть готовый? ;)
Так варнинги были из-за присваивания внутри while, вроде break здесь не причем.
А о том, что так быстрее, в этой ситуации на 2-х проверках конечно бессмысленно о каком то выигрыше в скорости говорить, я просто взял себе за правило, всегда писать сравнение со строкой без привидения типов, т.к. это гораздо быстрее при сравнении разных типов, но тут typeof выдает строку, поэтому наверное, никакой разницы не будет в скорости, поспешил я написать :-)
>из-за присваивания
Конечно из-за присваивания, мне там виделось что-то проще… вроде 'while (node && node.nodeType != 1)...', дабы не заходить внутрь, не брэкать, не делать безусловный 'do', а заодно убежать от ворнингов, убрав присвоение из 'while'…

>без привидения типов
Строгое стравнение выкидывает 'false' для значений разных типов. Нестрогое сравнение также может не конвертировать значения разных типов (undefined, null), в остальных случаях конвертирует, что само собой затратно по сравнению со строгим сравнением, чем и объясняется скорость в этом случае. В отношения значений одного и того же типа алгоритм обоих сравнений одинаков (буква в букву), в частности для 'typeof' при сравнении строки со строкой, теоретически они должны работать одинаково. Практически же энная реализация может учудить, сделав что-то быстрее или медленнее, но это скорее исключение из правил, на которое можно было бы ориентироваться, если бы была всем вокруг известна ужасающая разница на популярном движке (вроде «сверхбыстрой» конкатенации у IE)…
О, написал про IE, но на 8-ке не проверял, сказал по памяти, под рукой нет, может уже исправили. ???
Что исправили? children? Нет, IE8RC1 возвращает узел с комментарием при использовании children :-(
Жаль, значит укоренился баг…
node.getElementsByTagName("*").length — это не количество дочерних узлов. У дочерних узлов могут быть дочерние узлы, которые считать не надо.
Имелась ввиду проверка наличия дочерних элементов по аналогии с hasChildNodes, который проверяет наличие дочерних узлов, т.к. текстовые узлы не могут содержать дочерние узлы, то проверка:
node.getElementsByTagName("*").length
всегда верно будет показывать факт наличия дочерних элементов, но не всегда правильно их количество.
Перефразировал предложение в статье.
Sign up to leave a comment.

Articles