Подтвердить что ты не робот

Определить функцию внутри другой функции в javascript

function foo(a) {
    if (/*some condition*/) {
        // perform task 1
        // perform task 3
    }
    else {
        // perform task 2
        // perform task 3
    }
}

У меня есть функция, структура которой аналогична приведенной выше. Я хочу абстрагировать задачу 3 на функцию bar(), но я хочу ограничить доступ этой функции только к области foo(a).

Чтобы достичь того, что я хочу, правильно ли изменить следующее?

function foo(a) {
    function bar() {
        // perform task 3
    }

    if (/*some condition*/) {
        // perform task 1
        bar();
    }
    else {
        // perform task 2
        bar();
    }
}

Если вышесказанное верно, bar() получает переопределение при каждом вызове foo(a)? (беспокоиться о трате ресурсов процессора здесь)

4b9b3361

Ответ 1

Да, то, что у вас есть, верно. Некоторые заметки:

  • bar создается при каждом вызове функции foo, но:
    • В современных браузерах это очень быстрый процесс. (Некоторые движки вполне могут скомпилировать код для него только один раз, а затем повторно использовать этот код с другим контекстом каждый раз; движок Google V8 [в Chrome и других местах] делает это в большинстве случаев.)
    • И в зависимости от того, что делает bar, некоторые движки могут определить, что они могут "встроить" его, полностью исключая вызов функции. V8 делает это, и я уверен, что это не единственный двигатель, который делает. Естественно, они могут сделать это только в том случае, если это не изменит поведения кода.
  • Воздействие на производительность, если таковое возникает при создании bar каждый раз, будет сильно различаться в зависимости от движков JavaScript. Если bar тривиален, он будет варьироваться от необнаружимого до довольно маленького. Если вы не вызываете foo тысячи раз подряд (например, из обработчика mousemove), я бы об этом не беспокоился. Даже если бы вы были, я бы беспокоился об этом, только если бы увидел проблему на более медленных двигателях. Вот тестовый сценарий, включающий операции DOM, который предполагает, что есть влияние, но тривиальное (вероятно, размытое DOM). Здесь тестовый пример, выполняющий чистые вычисления, который демонстрирует гораздо более высокое влияние, но, честно говоря, мы говорим о разнице в микросекундах, потому что даже увеличение на 92% на то, что происходит за микросекунды, все еще очень быстрый. До тех пор, пока вы не столкнулись с реальным воздействием, не о чем беспокоиться.
  • bar будет доступен только из функции, и у него есть доступ ко всем переменным и аргументам для этого вызова функции. Это делает эту модель очень удобной.
  • Обратите внимание, что поскольку вы использовали объявление функции, не имеет значения, куда вы помещаете объявление (top, bottom или middle &— до тех пор, пока оно находится на верхнем уровне функции, а не внутри оператора управления потоком, который синтаксическая ошибка), он определяется до запуска первой строки пошагового кода.

Ответ 2

Это то, для чего закрыты.

var foo = (function () {
  function bar() {
    // perform task 3
  };

  function innerfoo (a) { 
    if (/* some cond */ ) {
      // perform task 1
      bar();
    }
    else {
      // perform task 2
      bar();
    }
  }
  return innerfoo;
})();

Innerfoo (замыкание) содержит ссылку на панель, и только анонимная функция возвращает только ссылку на innerfoo, которая вызывается только один раз, чтобы создать закрытие.

Бар недоступен снаружи таким образом.

Ответ 3

var foo = (function () {
    var bar = function () {
        // perform task 3
    }
    return function (a) {

        if (/*some condition*/) {
            // perform task 1
            bar();
        }
        else {
            // perform task 2
            bar();
        }
    };
}());

Закрытие сохраняет область bar(), содержащуюся, возвращая новую функцию из самопроизвольной анонимной функции, устанавливает более видимую область видимости в foo(). Анонимная функция самоисполнения запускается ровно один раз, поэтому существует только один экземпляр bar(), и каждое выполнение foo() будет использовать его.

Ответ 4

Да, это прекрасно работает.

Внутренняя функция не воссоздается каждый раз при вводе внешней функции, но она повторно назначается.

Если вы проверите этот код:

function test() {

    function demo() { alert('1'); }

    demo();
    demo = function() { alert('2'); };
    demo();

}

test();
test();

он покажет 1, 2, 1, 2, а не 1, 2, 2, 2.

Ответ 5

Я создал jsperf для тестирования вложенных и не вложенных выражений и выражений функций и объявлений функций, и я был удивлен, увидев, что вложенные тесты выполняются в 20 раз быстрее, чем не вложенные. (Я ожидал противоположных или незначительных различий).

https://jsperf.com/nested-functions-vs-not-nested-2/1

Это на Chrome 76, macOS.