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

ли перемещение внутренней функции за пределы этой так, чтобы она не создавалась при каждом вызове функции, было бы микрооптимизацией?

В этом конкретном случаеdoMoreStuff функция используется только внутриdoStuff, Должен ли я беспокоиться о наличии таких локальных функций?

function doStuff() {
    var doMoreStuff = function(val) {
         // do some stuff
    }

    // do something
    for (var i = 0; i < list.length; i++) {
         doMoreStuff(list[i]);
         for (var  j = 0; j < list[i].children.length; j++) {
              doMoreStuff(list[i].children[j]);
         }
    }
    // do some other stuff

}

Актуальным примером будет сказать:

function sendDataToServer(data) {
    var callback = function(incoming) {
         // handle incoming
    }

    ajaxCall("url", data, callback);

} 
 davin20 янв. 2011 г., 14:24
вероятно. но есть и другие соображения - в этом примере замыкание, которое вы создаете с помощью находящейся внутри функции, неоценимо, оно позволяет вам инкапсулировать все другие локальные переменные, которые у вас есть, без необходимости передавать их в качестве параметров или повторной обработки чего-либо.

Ответы на вопрос(4)

Решение Вопроса

что это подпадает под категорию «микрооптимизация». Я бы сказал нет.

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

Если вы не хотите иметь «вспомогательную функцию» в глобальной области видимости, но избегаете ее воссоздания, вы можете обернуть ее так:

var doStuff = (function() {
    var doMoreStuff = function(val) {
         // do some stuff
    }
    return function() {
        // do something
        for (var i = 0; i < list.length; i++) {
            doMoreStuff(list[i]);
        }
        // do some other stuff 
    }
}());

Поскольку возвращаемая функция является замыканием, она имеет доступ кdoMoreStuff, Обратите внимание, что внешняя функция выполняется немедленно ((function(){...}()) ).

Или вы создаете объект, который содержит ссылки на функции:

var stuff = {
    doMoreStuff: function() {...},
    doStuff: function() {...}
};

Более подробную информацию об инкапсуляции, шаблонах создания объектов и других концепциях можно найти в книге.Шаблоны JavaScript.

 Raynos20 янв. 2011 г., 14:24
Это очень интересная концепция. Использование замыканий, чтобы заставить его действовать как статический и приватный.
 Raynos20 янв. 2011 г., 14:58
Я знаком со вторым, но «встроенные» функции с помощью таких замыканий - это что-то новое для меня.
 Felix Kling20 янв. 2011 г., 14:28
@Raynos: Да, он часто используется для инкапсуляции данных, определения частных членов объектов и т. Д. В зависимости от того, насколько вы знакомы с JavaScript, я рекомендую книгуJavaScript Patterns.

что существует множество неучтенных переменных, поэтому не комментируйте очевидное, но в любом случае это интересно):

count = 0;
t1 = +new Date();
while(count < 1000000) {
  p = function(){};
  ++count;
}
t2 = +new Date();
console.log(t2-t1); // milliseconds

Это может быть оптимизировано путем перемещения приращения к условию, например (сокращает время работы примерно на 100 миллисекунд, хотя это не влияет наразница между созданием функции и без нее, так что это не очень актуально)

Запуск 3 раза дал:

913
878
890

Затем закомментируйте строку создания функции, 3 прогона дали:

462
458
464

Таким образом, чисто на 1000 000 пустых созданий функций вы добавляете около половины секунды. Даже если предположить, что ваш оригинальный код выполняется на портативном устройстве 10 раз в секунду (скажем, общая производительность устройств составляет 1/100 от этого ноутбука, что преувеличено - вероятно, ближе к 1/10, хотя и обеспечит хорошую верхнюю границу) , это эквивалентно 1000 созданиям функций в секунду на этом компьютере, что происходит за 1/2000 секунды. Таким образом, каждую секунду портативное устройство добавляет дополнительную нагрузку на 1/2000 секунды обработки ... полмисекунды в секунду - не очень много.

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

 Raynos20 янв. 2011 г., 14:56
И если вы сравните его с телом функции или тела цикла, которое выполняет значимые вычисления, разница лежит в границе статистической погрешности дат.
 Raynos20 янв. 2011 г., 15:32
То, что я пытался сказать, было то, что я думал, что это была слегка значимая оптимизация. Я не особо экономлю. Я всегда думал, что это плохая практика.
 davin20 янв. 2011 г., 15:03
@Raynos, я не знаю, сколько тестов вы сделали, хотя тестирование с большим телом цикла не помогло бы. если вы сохраняете минимальное тело цикла, вы можете более точно измерить эффект создания функции, тем самым_минимизируя_ эффект ошибок даты. это плюс тот факт, что вы запускаете тест много раз, и вы получаете точную оценку. моя точка зрения заключается в том, что тело цикла не имеет значения, ваш вопрос, по сути, сколько я могу сэкономить, изменяя мой код, и ответ заключается в том, сколько времени создаст стоимость функций, которая лучше всего измеряется, как я описал.

как часто вызывается функция. Если это функция OnUpdate, которая вызывается 10 раз в секунду, это приличная оптимизация. Если он вызывается три раза на страницу, это микрооптимализация.

Хотя это удобно, определения вложенных функций никогда не нужны (их можно заменить дополнительными аргументами для функции).

Пример с вложенной функцией:

function somefunc() {
    var localvar = 5

    var otherfunc = function() {
         alert(localvar);
    }

    otherfunc();
}

То же самое, теперь вместо аргумента:

function otherfunc(localvar) {
    alert(localvar);
}

function somefunc() {
    var localvar = 5

    otherfunc(localvar);
}
 orlp20 янв. 2011 г., 14:25
Конечно, подожди :)
 Raynos20 янв. 2011 г., 14:24
Можете ли вы объяснить, как я могу избежать вложенных функций. Я в основном использую их, чтобы сохранить код СУХИМЫМ, и потому что их использование вне этой конкретной функции просто добавляет больше к глобальному пространству имен, где оно действительно должно быть локальным. В идеале я хочу статическую функцию, но это невозможно.
 Raynos20 янв. 2011 г., 14:57
Причина, по которой я хочу, чтобы локальные функции в основном содержалиotherfunc внутриsomefunc потому что он используется только там, а встраивание становится немного уродливым.

вую очередь заключается в том, что вы делаете свой код чище, более понятным и более читабельным. Функции добавляют семантическую границу к разделам кода. Каждая функция должна делать только одну вещь, и она должна делать это чисто. Поэтому, если вы обнаружите, что ваши функции выполняют несколько задач одновременно, у вас есть кандидатура для рефакторинга в несколько подпрограмм.

Оптимизируйте только тогда, когда у вас что-то работает слишком медленно (если это еще не работает, оптимизировать рано. Период). Помните, никто никогда не платил дополнительно за программу, которая была быстрее, чем их потребности / требования ...

редактировать: Учитывая, что программа еще не закончена, это также преждевременная оптимизация. Почему это плохо? Ну, во-первых, вы проводите время, работая над чем-то, что может не иметь значения в долгосрочной перспективе. Во-вторых, у вас нет базовой линии, чтобы увидеть, улучшили ли ваши оптимизации что-либо в реалистическом смысле. В-третьих, вы снижаете удобство сопровождения и читаемость еще до того, как вы его запустите, поэтому запускать его будет сложнее, чем если бы вы использовали чистый лаконичный код. В-четвертых, вы не знаете, понадобится ли вамdoMoreStuff где-то еще в программе, пока вы не закончили ее и не поняли все свои потребности (возможно, длинный сценарий, зависящий от точных деталей, но не выходящий за рамки возможного).

Есть причина, по которой Донналд Кнут сказалПреждевременная оптимизация - корень всего зла...

 orlp20 янв. 2011 г., 14:24
* вечно :) 15 символов
 ircmaxell20 янв. 2011 г., 14:26
Спасибо @nightcracker. исправлено...

Ваш ответ на вопрос