Как вы обнаружили, разные вещи являются проблемами в разных реализациях.По моему опыту, если не делать действительно глупых вещей, нет смысла беспокоиться о том, чтобы оптимизировать код JavaScript, чтобы он был быстрым до тех пор, пока вы не столкнетесь с конкретной проблемой производительности при тестировании в целевых браузерах.Такие простые вещи, как обычная оптимизация «обратный отсчет до нуля» (for (i = length - 1; i >= 0; --i)
вместо for (i = 0; i < length; ++i)
), даже не надежны во всех реализациях.Поэтому я склонен придерживаться написания достаточно понятного кода (потому что я хочу быть добрым с тем, кто должен его поддерживать, что часто бывает со мной), а затем беспокоиться об оптимизации, если и когда.
Тем не менее, глядячерез статью Google , на которую tszming ссылался в его / ее ответе , напомнили мне, что есть некоторые вещи с производительностью, о которых я склонен помнить при написании кода изначально.Вот список (некоторые из этой статьи, некоторые нет):
Когда вы создаете длинную строку из множества фрагментов, неожиданно вы обычно получаете лучшую производительность, если вы наращиваетемассив фрагментов, а затем используйте метод Array#join
для создания окончательной строки.Я делаю это много, если создаю большой HTML-фрагмент, который добавлю на страницу.
Шаблон переменной частного экземпляра Крокфорда , хотякруто и мощно, дорого.Я склонен избегать этого.
with
стоит дорого и его легко понять.Избегайте этого.
Утечки памяти, конечно, дороги в конце концов.Их довольно легко создавать в браузерах, когда вы взаимодействуете с элементами DOM.См. Статью для более подробной информации, но в основном подключите обработчики событий, используя хорошую библиотеку, такую как jQuery, Prototype, Closure и т. Д. (Потому что это особенно уязвимая область, и библиотеки помогают), и избегайте хранения ссылок на элементы DOM в других DOMэлементы (прямо или косвенно) через свойства expando.
Если вы создаете значительное динамическое отображение содержимого в браузере, innerHTML
в большинстве случаев намного быстрее, чем при использованииМетоды DOM (createElement
и appendChild
).Это связано с тем, что эффективный синтаксический анализ HTML во внутренних структурах - это , что делают браузеры , и они делают это очень быстро, используя оптимизированный скомпилированный код, пишущий непосредственно в свои внутренние структуры данных.Напротив, если вы создаете значительное дерево с использованием методов DOM, вы используете интерпретируемый (обычно) язык, говорящий с абстракцией, которую браузер должен преобразовать, чтобы соответствовать его внутренним структурам.Некоторое время назад я провел несколько экспериментов , и разница была примерно на порядок (в пользу innerHTML
).И, конечно, если вы создаете большую строку для присвоения innerHTML
, см. Совет выше - лучше всего построить фрагменты в массиве, а затем использовать join
.
Кэшируйте результаты известных медленных операций, но не переусердствуйте, а храните вещи столько, сколько вам нужно.Имейте в виду стоимость сохранения ссылки и стоимость ее повторного поиска.
Я неоднократно слышал, как люди говорят, что доступ к переменным из ограниченной области (глобальные переменныеконечный пример этого, конечно, но вы можете сделать это с замыканиями в других областях) медленнее, чем доступ к локальным, и, безусловно, это будет иметь смысл в чисто интерпретированной, неоптимизированной реализации из-за способа определения цепочки областей действия,Но я никогда не видел, чтобы это оказалось значительным отличием на практике .( Ссылка на простой быстрый и грязный тест ) Фактические глобальные переменные являются особыми, поскольку они являются свойствами объекта 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 три раза в каждый цикл : сначала проверить, находится ли индекс в границах, затем при проверке, имеет ли элемент класс bar, а затем при настройке стиля.
Это просто безумие и безумие, независимо от того, в каком браузере он работает. Вы явно хотите кратко кэшировать этот поиск:
list = $$('.foo');
for (i = 0; i < list.length; ++i) {
if (list[i].hasClass("bar")) { // I forget what this actually was
list[i].setStyle({/* ... */});
}
}
... но продолжать его (например, работать в обратном направлении до нуля) бессмысленно, он может быть быстрее в одном браузере и медленнее в другом.