Родитель(), более быстрая альтернатива?
Я работаю с панелью divs, и каждый div имеет дерево, с которым расположены кнопки. Каждый раз, когда я должен знать, какой id этого div, я использую parent() alot.
В основном я делаю $(this).parent().parent().parent()
, чтобы найти идентификатор div, чтобы я мог установить для него переменные. Приложение основано на идентификаторе каждого div.
Рассматривать медленное использование parent() до 3 раз, но в значительной степени для каждой функции?
Есть ли другая альтернатива?
Я ищу что-то вроде эталонных тестов, которые показывают, что быстрее.
Вот пример дерева:
<div id="6179827893" class="dashdiv">
<div class="buttons">
<li><a href="#" class="btn1">Button 1</a></li>
<li><a href="#" class="btn2">Button 2</a></li>
<li><a href="#" class="btn3">Button 3</a></li>
<li><a href="#" class="btn4">Button 4</a></li>
<li><a href="#" class="btn5">Button 5</a></li>
<li><a href="#" class="btn6">Button 6</a></li>
</div>
<div class="dashcontent">
....
</div>
</div>
Ответы
Ответ 1
У вас есть несколько вариантов для достижения того же эффекта.
Контрольный показатель: http://jsperf.com/parents-method. Согласно этому эталону, мой метод примерно в 100 раз быстрее, чем ваш метод.
Method (see below) : Operations per second (higher is better)
parentNode3x : 4447k
$(parentNode3x) : 204K
$().closest : 35k
$().parents : 9k
$().parent()3x : 44k
// Likely the fastest way, because no overhead of jQuery is involved.
var id = this.parentNode.parentNode.parentNode.id;
// Alternative methods to select the 3rd parent:
$(this.parentNode.parentNode.parentNode) // Native DOM, wrapped in jQuery
// Slowpokes
$(this).closest('.dashdiv') // Hmm.
$(this).parents('.dashdiv:first') // Hmm...
Ответ 2
Вам может быть лучше использовать .closest()
, например: $(this).closest('.dashdiv')
Это не так быстро с точки зрения двигателя, поскольку вы все еще перебираете слои DOM, но это более понятно новичкам, а также более коротким.
Комментарий
Если вам нужна чистая скорость, вы можете также полностью пропустить jQuery и вместо этого использовать node.parentNode
. Но это приводит к ничтожным проблемам подсчета циклов, и я думаю, что это академический.
Если вы пишете высокопроизводительный код для крупного производства, например, коммерческую поисковую систему или поставщик веб-почты, то подсчет циклов важен, потому что любая небольшая оптимизация умножается тысячами раз. При всем моем уважении, я сомневаюсь, что вы пишете такой код.
Если вы пишете то, что может пострадать несколько человек за раз, в лучшем случае, небольшие оптимизации - это интеллектуальное упражнение, которое не повлияет на результаты каким-либо заметным образом. Вам нужно будет повысить эффективность кода на сотни миллисекунд, прежде чем любой пользователь даже начнет замечать, и этот код не собирается этого делать.
Вместо этого гораздо важнее подумать о следующем разработчике, который будет смотреть на ваш код. Для этого разработчика важно иметь четкий, хорошо написанный код, который немедленно сообщает, что он делает. Глазуристые цепочки таких методов, как parent().parent().parent()
, могут скрывать и путать других разработчиков, не говоря уже о node.parentNode.parentNode.parentNode
- вот почему .closest()
был создан в первую очередь. Он ясен, краток и не заметно эффективнее, чем цепи, которые он заменяет. 999 раз из тысячи, это то, как вы должны идти.
Ответ 3
Во-первых, не оптимизируйте преждевременно. Если это не вызовет проблемы (и тщательно протестируйте все средства на разных платформах), не беспокойтесь об этом.
Существует возможная оптимизация: используйте собственные свойства DOM:
var id = this.parentNode.parentNode.parentNode.id;
Обратите внимание, что самый лучший способ jQuery для этого (который будет медленнее, но это может быть не проблема) с closest
:
$(this).closest('div.dashdiv').prop('id');
Ответ 4
Если обработчики в настоящее время находятся в элементах <a>
, поместите их вместо элементов .dashdiv
.
Тогда вы можете сделать this.id
, если e.target
был элементом <a>
.
$('.dashdiv').click(function(e) {
if( e.target.nodeName.toLowerCase() === 'a' ) {
alert( this.id );
}
});