Вложенные функции и производительность в JavaScript?

Некоторые из коллег говорят, что вложенные функции плохо влияют на производительность, и я хотел спросить об этом.

Допустим, у меня есть функция:

function calculateStuff() {
    function helper() {
    // helper does things
    }
    // calculateStuff does things
    helper();
}

helper - это закрытая функция, которая используется только внутри calcStuff. Вот почему я хотел инкапсулировать это в CalculateStuff.

Разве это хуже, чем делать:

function helper() {

}

function calculateStuff() {
    helper();
}

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

2 ответа

Решение

С вашим первым кодом, при каждом вызове calculateStuffновая копия helper будет создан.

С вашим вторым кодом все звонки будут делиться одинаково helper, но это загрязнит внешнюю сферу.

Если вы хотите использовать повторно helper без загрязнения внешней области вы можете использовать IIFE:

var calculateStuff = (function () {
  function helper() {
    // helper does things
  }
  return function() {
    // calculateStuff does things
    helper();
  }
})();

Теоретически, это может повлиять на производительность в том смысле, что вам нужно создавать новый контекст замыкания для помощника каждый раз, когда вызывается Calculate (потому что он может ссылаться на переменные из входящей области).

Явполне уверен, что JIT-компилятор в большинстве движков JavaScript должен быть в состоянии сказать, что вы на самом деле не обращаетесь к каким-либо переменным из родительского контекста, и просто пропустите связывание всех этих значений. Возможно, я упускаю какой-то крайний случай, когда это вообще невозможно, но кажется достаточно простым.

В любом случае, мы говорим о наносекундах накладных расходов на одну итерацию, поэтому, если ваш код не выполняетсямного, вы никогда не заметите разницу во времени. Если сомневаетесь, профилируйте его и проверьте...


Я решил последовать моему собственному совету и профилировать это на jsperf с Safari 9. Я использовал функции "ничего не делать", как предусмотрено в исходном вопросе, чтобы выделить накладные расходы при простом вызове вложенной функции:

Вложенные функции: 136 000 000 вызовов в секунду

Плоские функции: 1 035 000 000 ккал в секунду

Версия IIFE от Oriol: 220 000 000 ккал в секунду

Очевидно, что плоские функции намного быстрее, чем любая из альтернативных версий. Однако подумайте о величине этих чисел - даже "медленная" версия добавляет к времени выполнения только 0,007 микросекунды. Если вы выполняете какие-либо вычисления или манипуляции с DOM в этой функции, это абсолютно затмит накладные расходы на вложенную функцию.

Другие вопросы по тегам