Вкладена функція JavaScript


96

Я отримав шматок коду для javascript, якого я просто не розумію:

function dmy(d) {
    function pad2(n) {
        return (n < 10) ? '0' + n : n;
    }

    return pad2(d.getUTCDate()) + '/' +
       pad2(d.getUTCMonth() + 1) + '/' +
       d.getUTCFullYear();
}

function outerFunc(base) {
    var punc = "!";

    //inner function
    function returnString(ext) {
       return base + ext + punc;
    }

    return returnString;
}

Як можна визначити функцію в межах іншої функції? Чи можемо ми викликати pad2 () поза межами моєї функції ()?

Будь ласка, покладіть на це світло. Дякую


13
функції можуть бути створені всередині функцій. Це цілком справедливо.
0x499602D2

Відповіді:


140

Функції - це інший тип змінних у JavaScript (з певними нюансами). Створення функції в рамках іншої функції змінює область дії функції так само, як і зміну області дії змінної. Це особливо важливо для використання із закритими системами для зменшення загального забруднення простору імен.

Функції, визначені в іншій функції, не будуть доступні за межами функції, якщо вони не були приєднані до об'єкта, який доступний за межами функції:

function foo(doBar)
{
  function bar()
  {
    console.log( 'bar' );
  }

  function baz()
  {
    console.log( 'baz' );
  }

  window.baz = baz;
  if ( doBar ) bar();
}

У цьому прикладі функція baz буде доступна для використання після fooзапуску функції, оскільки вона замінена window.baz. Функція bar не буде доступна для будь-якого іншого контексту, крім областей, що містяться у fooфункції.

як інший приклад:

function Fizz(qux)
{
  this.buzz = function(){
    console.log( qux );
  };
}

FizzФункція призначена як конструктор , так що при запуску він призначає buzzфункцію для новоствореного об'єкта.


Що таке window.baz = baz? Чому ця лінія доступна?
Ziyang Zhang

@ZiyangZhang, абзац після цього кодового блоку має пояснення, чи була якась незрозуміла частина?
zzzzBov

35

Це називається закриттям .

В основному, функція, визначена в іншій функції, доступна лише в межах цієї функції. Але може бути переданий як результат, і тоді цей результат може бути викликаний.

Це дуже потужна функція. Ви можете побачити більше пояснень тут:

javascript_closures_for_dummies.html дзеркало на Archive.org


13
function x() {}

еквівалентно (або дуже схоже) на

var x = function() {}

якщо я не помиляюся.

Тож нічого смішного не відбувається.


8
Перший синтаксис буде переміщено на початок документа. тому можна викликати функцію 'x' перед ініціалізацією функції.
Том

10
Перший синтаксис також забезпечить вам набагато приємніші сліди стека з названими функціями, другий доставить вам головний біль
TheZ

@TheZ Я думаю, що нещодавно Chrome додав налагодження назви функції до налагодження, щоб у вас не виникав такий самий головний біль, як раніше у звичайному випадку.
jinglesthula

@jinglesthula Так! Chrome додав це висновок про назву ще деякий час тому, і це дуже
вдячно

10

Екземпляр функцій дозволяється всередині та зовні функцій. Усередині цих функцій, як і змінні, вкладені функції є локальними і тому не можуть бути отримані із зовнішньої області.

function foo() {
    function bar() {
        return 1;
    }
    return bar();
}

fooманіпулює barвсередині себе. barне можна торкнутися з зовнішньої області, якщо це не визначено в зовнішній області.

Отже, це не спрацює:

function foo() {
    function bar() {
        return 1;
    }
}

bar(); // throws error: bar is not defined

4

Коли ви оголошуєте функцію всередині функції, внутрішні функції доступні лише в тому обсязі, в якому вони оголошені, або у вашому випадку їх pad2можна викликати лише вdmy області.

Усі змінні, що існують у dmy, видно у pad2, але це не відбувається навпаки: D


2

Цілком нормально в Javascript (і багатьох мовах) мати функції всередині функцій.

Не поспішайте вивчати мову, не використовуйте її на підставі того, що вона схожа на те, що ви вже знаєте. Я пропоную подивитися серію презентацій YUI Дугласа Крокфорда на Javascript, з особливим акцентом на Act III: Function the Ultimate (посилання на завантаження відео, слайди та стенограму)


0

function foo() {
  function bar() {
    return 1;
  }
}
bar();

Викине помилку. Оскільки barвизначено всередині foo, barбуде доступно лише всередині foo.
Для використання barвам потрібно запустити його всередину foo.

function foo() {
  function bar() {
    return 1;
  }
  bar();
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.