Как вы обнаружили, разные вещи являются проблемами в разных реализациях. По моему опыту, если не делать действительно глупых вещей, не стоит беспокоиться о том, чтобы оптимизировать ваш код JavaScript до тех пор, пока вы не столкнетесь с определенной проблемой производительности при тестировании в целевых браузерах. Такие простые вещи, как обычная оптимизация «отсчет до нуля» (for (i = length - 1; i >= 0; --i)
вместо for (i = 0; i < length; ++i)
), даже не являются надежными в реализации. Поэтому я склонен придерживаться написания кода, который достаточно ясен (потому что я хочу быть хорошим для тех, кто должен его поддерживать, что часто бывает у меня), а затем беспокоиться о оптимизации, если и когда.
Сказанное, просматривающее the Google article, что tszming, связанный с в his/her answer, напомнил мне, что есть некоторые вещи, которые я имею в виду при написании кода изначально. Вот список (некоторые из этой статьи, некоторые нет):
Когда вы создаете длинную строку из большого количества фрагментов, неожиданно вы обычно получить более высокую производительность, если вы строите массив фрагментов а затем используйте метод Array#join
для создания окончательной строки. Я делаю это много, если я создаю большой фрагмент HTML, который я буду добавлять на страницу.
Crockford private instance variable pattern, хотя и классный и мощный, стоит дорого. Я стараюсь избегать этого.
with
дорого и легко понять неправильно. Избегай это.
Утечки памяти, конечно же, дороги в конечном итоге. Их легко создавать в браузерах, когда вы взаимодействуете с элементами DOM. См. Статью для более подробной информации, но в основном, подключите обработчики событий с помощью хорошей библиотеки, такой как jQuery, Prototype, Closure и т. Д. (Потому что это особенно уязвимая область и библиотеки помогают) и избегайте хранения ссылок на элементы DOM на других DOM элементов (прямо или косвенно) через свойства expando.
Если вы строите значительное динамическое отображение контента в браузере, innerHTML
намного быстрее, в большинстве случаев, чем при использовании методов DOM (createElement
и appendChild
). Это связано с тем, что эффективный анализ HTML в их внутренних структурах - , что делают браузеры, и они делают это очень быстро, используя оптимизированный, скомпилированный код, записывающий непосредственно в свои внутренние структуры данных. Напротив, если вы создаете значительное дерево с помощью методов DOM, вы используете интерпретируемый (обычно) язык, говорящий с абстракцией, которую браузер должен переводить, чтобы соответствовать ее внутренним структурам. Я сделал a few experiments некоторое время назад, и разница была примерно на порядок (в пользу innerHTML
).И, конечно, если вы создаете большую строку для назначения innerHTML
, см. Подсказку выше — Лучше всего создавать фрагменты в массиве, а затем использовать join
.
Кэш результатов известных операций медленного действия, но не переусердствуйте и сохраняйте вещи только в том случае, если они вам понадобятся. Помните о стоимости сохранения ссылки и стоимости ее поиска.
Я уже неоднократно слышал, как люди говорят, что доступ к vars из области сдерживания (конечно, глобальный выбор будет конечным примером этого, но вы можете сделать это с закрытием в других областях) медленнее, чем доступ к локальным, и, конечно же, это будет иметь смысл в чисто интерпретированной, не оптимизированной реализации из-за того, как определяется цепочка областей. Но я никогда на самом деле не видел, что это оказалось существенной разницей на практике. (Link to simple quick-and-dirty test) Фактически globals являются особыми, поскольку они являются объектами объекта window
, который является объектом-хозяином и поэтому немного отличается от анонимных объектов, используемых для других уровней области. Но я ожидаю, что вы все равно избегаете глобалов.
Вот пример №6. Я действительно видел это в вопрос, связанный с Prototype несколько недель назад:
for (i = 0; i < $$('.foo').length; ++i) {
if ($$('.foo')[i].hasClass("bar")) { // I forget what this actually was
$$('.foo')[i].setStyle({/* ... */});
}
}
В Prototype, $$
делает дорогая вещь: Она ищет через дерево DOM подберет элементов (в данном случае, элементы с классом "Foo"). Приведенный выше код выполняет поиск DOM три раза по адресу каждый цикл: сначала проверьте, находится ли индекс в границах, а затем при проверке, имеет ли элемент класс «бар», а затем при настройке стиля.
Это просто сумасшедший, и это будет безумие, независимо от того, в каком браузере он работает. Вы явно хотите кэшировать, что поиск кратко:
list = $$('.foo');
for (i = 0; i < list.length; ++i) {
if (list[i].hasClass("bar")) { // I forget what this actually was
list[i].setStyle({/* ... */});
}
}
... но принимать его дальше (например, работа в обратном направлении до нуля) не имеет смысла, это может быть быстрее на одном браузере и медленнее на другой.
Переменные дешевые. Назначение также дешево, поскольку оно копирует только примитивные значения или ссылки в случае объектов. Я не думаю, что это может быть узким местом производительности. – galambalazs
@ galambalazs, делая что-то сотни тысяч раз, я думаю, что каждое задание имеет значение? – hvgotcodes
определенно проверьте это [предложение] (http://area51.stackexchange.com/proposals/11464/code-review?referrer=aWNm_PdciyFqjFW8CUacGw2 «обзор кода»).Это почти так, просто нужно немного больше поддержки :) – greatwolf