Вложенные функции и производительность в 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 в этой функции, это абсолютно затмит накладные расходы на вложенную функцию.