Блог Конфуция
Сказочно медленный className 03.04.2009

Как выяснилось, лучше выполнить кучу предварительных проверок в яваскрипте, и только потом, при крайней необходимости, трогать className. Дело в том, что это свойство затратно не только записать, но и прочитать. Тормозить будет даже в том случае, когда фактическое значение не меняется (node.className = node.className).

Почему так происходит, легко понять из кода, которым обвязывается каждое обращение к свойству оборачиваемого объекта (в данном случае обернут элемент DOM-дерева). Такая обвязка, как правило, состоит из внушительного куска кода, который выясняет, какое именно свойство вызвано, а потом ищет, как это свойство прочитать или записать. Поиск чаще используется простой, перебором. Затем, управление передается дальше. Наверняка, это будет вызов некоторого метода. Метод сделает что-то свое (возможно, просто возвратит строку, а может и другие методы повызывает). И напоследок, результат работы метода необходимо обернуть в подходящий яваскриптовый объект. В нашем случае это строка. А строку еще надо создать, выделить память под символы (предварительно посчитав, сколько байт нужно), скопировать в нее данные, вернувшиеся из метода (почти наверняка, перекодировав в UTF-16), и только потом возвратить управление яваскрипту.

Пример грустный от того, что в нем перечислена куча действий, от которых можно отказаться. Однако, отказаться от них очень непросто, и это потребует от разработчиков браузера много терпения и желания сделать людям быстро. Такие оптимизации как раз ведут к тому, что называется быстрым ДОМом (faster DOM).

Мы можем немного помочь разработчикам браузеров, если научим свою страничку кешировать значение className. Таким образом, этот код в фаерфоксе будет быстрее:


cache = 'a'
cache = className = cache + ' b'
чем этот:

className += ' b'

Когда появится свободное время, дополню пост парой бенчмарков, а пока, остается верить мне на слово ;)

Теги:
  • клиент
  • className
  • DOM
  • performance
Очень жду ваших комментариев на почту или на гитхаб.