Javascript конструкции, чтобы избежать? - PullRequest
0 голосов
/ 03 октября 2010

Я пишу алгоритм JS. Его сверкает быстро в хроме, а собака медленно в FF. В Chrome Profiler я трачу <10% на метод, в FF этот же метод составляет 30% времени выполнения. Существуют ли конструкции javascript, которых следует избегать, потому что они действительно медленны в том или ином браузере? </p>

Одна вещь, которую я заметил, заключается в том, что такие вещи, как простое объявление переменных, могут быть дорогими, если вы делаете это достаточно. Я ускорил свой алгоритм, заметный, не делая такие вещи, как

var x = y.x;
dosomthing(x);

и просто делаю

dosomething(y.x)

например.

Ответы [ 3 ]

5 голосов
/ 03 октября 2010

Как вы обнаружили, разные вещи являются проблемами в разных реализациях.По моему опыту, если не делать действительно глупых вещей, нет смысла беспокоиться о том, чтобы оптимизировать код JavaScript, чтобы он был быстрым до тех пор, пока вы не столкнетесь с конкретной проблемой производительности при тестировании в целевых браузерах.Такие простые вещи, как обычная оптимизация «обратный отсчет до нуля» (for (i = length - 1; i >= 0; --i) вместо for (i = 0; i < length; ++i)), даже не надежны во всех реализациях.Поэтому я склонен придерживаться написания достаточно понятного кода (потому что я хочу быть добрым с тем, кто должен его поддерживать, что часто бывает со мной), а затем беспокоиться об оптимизации, если и когда.

Тем не менее, глядячерез статью Google , на которую tszming ссылался в его / ее ответе , напомнили мне, что есть некоторые вещи с производительностью, о которых я склонен помнить при написании кода изначально.Вот список (некоторые из этой статьи, некоторые нет):

  1. Когда вы создаете длинную строку из множества фрагментов, неожиданно вы обычно получаете лучшую производительность, если вы наращиваетемассив фрагментов, а затем используйте метод Array#join для создания окончательной строки.Я делаю это много, если создаю большой HTML-фрагмент, который добавлю на страницу.

  2. Шаблон переменной частного экземпляра Крокфорда , хотякруто и мощно, дорого.Я склонен избегать этого.

  3. with стоит дорого и его легко понять.Избегайте этого.

  4. Утечки памяти, конечно, дороги в конце концов.Их довольно легко создавать в браузерах, когда вы взаимодействуете с элементами DOM.См. Статью для более подробной информации, но в основном подключите обработчики событий, используя хорошую библиотеку, такую ​​как jQuery, Prototype, Closure и т. Д. (Потому что это особенно уязвимая область, и библиотеки помогают), и избегайте хранения ссылок на элементы DOM в других DOMэлементы (прямо или косвенно) через свойства expando.

  5. Если вы создаете значительное динамическое отображение содержимого в браузере, innerHTML в большинстве случаев намного быстрее, чем при использованииМетоды DOM (createElement и appendChild).Это связано с тем, что эффективный синтаксический анализ HTML во внутренних структурах - это , что делают браузеры , и они делают это очень быстро, используя оптимизированный скомпилированный код, пишущий непосредственно в свои внутренние структуры данных.Напротив, если вы создаете значительное дерево с использованием методов DOM, вы используете интерпретируемый (обычно) язык, говорящий с абстракцией, которую браузер должен преобразовать, чтобы соответствовать его внутренним структурам.Некоторое время назад я провел несколько экспериментов , и разница была примерно на порядок (в пользу innerHTML).И, конечно, если вы создаете большую строку для присвоения innerHTML, см. Совет выше - лучше всего построить фрагменты в массиве, а затем использовать join.

  6. Кэшируйте результаты известных медленных операций, но не переусердствуйте, а храните вещи столько, сколько вам нужно.Имейте в виду стоимость сохранения ссылки и стоимость ее повторного поиска.

  7. Я неоднократно слышал, как люди говорят, что доступ к переменным из ограниченной области (глобальные переменныеконечный пример этого, конечно, но вы можете сделать это с замыканиями в других областях) медленнее, чем доступ к локальным, и, безусловно, это будет иметь смысл в чисто интерпретированной, неоптимизированной реализации из-за способа определения цепочки областей действия,Но я никогда не видел, чтобы это оказалось значительным отличием на практике .( Ссылка на простой быстрый и грязный тест ) Фактические глобальные переменные являются особыми, поскольку они являются свойствами объекта 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({/* ... */});
    }
}

... но продолжать его (например, работать в обратном направлении до нуля) бессмысленно, он может быть быстрее в одном браузере и медленнее в другом.

1 голос
/ 03 октября 2010

Я не думаю, что это действительно производительность, но что-то, чего следует избегать наверняка, если вы действительно не знаете, что происходит:

var a = something.getArrayOfWhatever();
for (var element in a) {
  // aaaa! no!!  please don't do this!!!
}

Другими словами, следует избегать использования конструкции for ... in для массивов. Даже при переборе свойств объекта это сложно.

Кроме того, мое любимое, что следует избегать, - избегать пропуска var при объявлении локальных переменных!

1 голос
/ 03 октября 2010
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...