


Кэш. Разгоняем jQuery. Практическое приложение. Оптимизация структуры веб-страниц
Кэш
События
Внутреннее кэширование
Кэш у jQuery крайне не развит, если не сказать отсутствует, поэтому кэшируется только предыдущий элемент, выбранный в цепочке. Это можно наглядно рассмотреть на двух примерах.
Ситуация такая, вы работаете со списком, у вас если один из элементов li для того, чтобы получить все элементы, включая текущий, надо выбрать всех братьев (все, у кого родитель – это родитель текущего) этого элемента и добавляем его самого
$("#id").siblings().add("#id")
Так как он – прошлый элемент, с которым работали в цепочке вызовов, мы можем взять его из кэша.
$("#id").siblings().andSelf()
Конечно, в данном конкретном случаи быстрее было бы сделать
$("#id").parent().children()
Потому что siblings это и есть выбор всех детей родителя. Но принцип использования этот пример иллюстрирует нормально.
Второй пример использования кэша это простой возврат к предыдущей выборке, вместо того чтобы размазывать код на три строчки
var elt = $("#id");
elt.children().css({/**/})
elt.click();
Можно после работы с детьми вернуться обратно к родителю и работать с ним дальше
$("#id").children().css({/**/}).end().click()
Кэширование селекторов
Поскольку кэш так слабо развит, селекторы нужно кэшировать вручную. Давайте рассмотрим, например, вот такой код
for(var i=0;i<1000;i++)
$("ul").append("<li>"+i+"</li>")
Все работает и выглядит красиво, но это можно оптимизировать, если вынести выборку за пределы цикла, добавление новых элементов будет проходить быстрее
var elts = $("ul");
for(var i=0;i<1000;i++)
elts.append("<li>"+i+"</li>")
Буферизация
Но и это еще не все, этот код можно заставить работать еще быстрее. Каждый раз, делая append, мы заставляем обновиться DOM-дерево и заставляем браузер перерисовать страницу. Этого можно избежать, придерживая вставку в DOM-дерево.
var str = "";
for(var i=0;i<1000;i++)
str += "<li>"+i+"</li>"
$("ul").html(str);
Дело в том, что функции для работы с DOM-деревом у jQuery самые «тяжелые» (http://mabp.kiev.ua/2009/03/29/jquery-profiling/). Это просто объясняется. Все html ноды, на которые повешены события через jQuery, имеют в себе атрибут с объектом jQuery. При удалении этих нод нужно следить, чтобы не было утечек памяти, и удалять эти атрибуты перед удалением ноды. В результате функции html и text вызывают функции полной очистки и только потом вставки нового содержимого.
jQuery(DOMElement).empty().append(text)
Функция empty выбирает все ноды и по очереди удаляет
jQuery(DOMElement).children().remove()
А функция remove уже заботится, чтобы из элементов были удалены все дополнительные данные и события
Джон Ресиг (John Resig) утверждал, что знает способ быстро удалить все это и что улучшит эти методы, но что-то воз и ныне там. Поэтому будем ждать улучшенных функций уже в jQuery 1.4
Создание «на лету»
Прошлый пример на самом деле был нужен для того, чтобы подобраться поближе к интересненому. Часто приходится создавать какие-то вспомогательные дивы, естественно, нас интересует самый эргономичный способ это сделать. Казалось бы, в чем проблема: кинул кусок html кода, и jQuery сама все сделала. Возьмем самый простой и банальный пример надо создать пустой див.
$("<div></div>")
или
$("<div/>")
Второй вариант в 5 раз быстрее первого. Но это, естественно, не все, что если нам надо создать не пустой див, а содержащий текст, из прошлых заметок станет ясно, что функция text тяжелая, и выгоды от нее не будет, и стоит создавать див, как есть.
$("<div>text</div>")
А не создавать, а потом добавлять текст
$("<div/>").text("text")
Но это не каcается создания атрибутов, для них используются намного более «легкие» функции attr/css/addClass (http://mabp.kiev.ua/2009/03/29/jquery-profiling/), вот тут-то и имеет смысл вместо
$("<div style='background:red;'/>")
писать
$("<div/>").css({background:'red'});
это даст небольшой, но выигрыш.