Zagnieżdżona funkcja JavaScript


97

Mam kawałek kodu javascript, którego po prostu nie rozumiem:

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;
}

Jak można zdefiniować funkcję w ramach innej funkcji? Czy możemy wywołać pad2 () spoza funkcji my ()?

Proszę, rzuć na to trochę światła. Dzięki


13
funkcje można tworzyć wewnątrz funkcji. To jest całkowicie słuszne.
0x499602D2

Odpowiedzi:


141

Funkcje to inny typ zmiennych w JavaScript (oczywiście z pewnymi niuansami). Utworzenie funkcji w ramach innej funkcji zmienia zakres funkcji w taki sam sposób, jak zmieniałby zakres zmiennej. Jest to szczególnie ważne w przypadku użycia z zamknięciami w celu zmniejszenia całkowitego zanieczyszczenia globalnej przestrzeni nazw.

Funkcje zdefiniowane w innej funkcji nie będą dostępne poza funkcją, chyba że zostaną dołączone do obiektu, który jest dostępny poza funkcją:

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

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

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

W tym przykładzie funkcja baz będzie dostępna do użycia po uruchomieniu foofunkcji, ponieważ została nadpisana window.baz. Funkcja paska nie będzie dostępna dla żadnego kontekstu innego niż zakresy zawarte w foofunkcji.

jako inny przykład:

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

FizzFunkcja została zaprojektowana jako konstruktor tak, że po uruchomieniu, przypisuje się buzzfunkcję do nowo utworzonego obiektu.


Co to jest window.baz = baz? Dlaczego ta linia m? Ke baz jest dostępna?
Ziyang Zhang

@ZiyangZhang, akapit po tym bloku kodu zawiera wyjaśnienie, czy była jakaś konkretna część, która jest niejasna?
zzzzBov


13
function x() {}

jest równoważny (lub bardzo podobny) do

var x = function() {}

chyba że się mylę.

Więc nie dzieje się nic zabawnego.


8
Pierwsza składnia zostanie przeniesiona na początek dokumentu. więc możliwe jest wywołanie funkcji „x” przed jej zainicjalizowaniem.
Tom

10
Pierwsza składnia zapewni również znacznie ładniejsze ślady stosu z nazwanymi funkcjami, druga przyprawi o ból głowy
TheZ

@TheZ Myślę, że Chrome niedawno dodał wnioskowanie o nazwie funkcji do debugowania, aby nie odczuwać tego samego bólu głowy, co wcześniej w typowym przypadku.
jinglesthula

@jinglesthula Yes! Chrome dodał to wnioskowanie o nazwie jakiś czas temu i jest to bardzo cenione :)
TheZ,

10

Tworzenie instancji funkcji jest dozwolone wewnątrz i na zewnątrz funkcji. Wewnątrz tych funkcji, podobnie jak zmienne, funkcje zagnieżdżone są lokalne i dlatego nie można ich uzyskać z zewnętrznego zakresu.

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

foomanipuluje barw sobie. barnie można dotknąć z zakresu zewnętrznego, chyba że jest zdefiniowany w zakresie zewnętrznym.

Więc to nie zadziała:

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

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

4

Kiedy deklarujesz funkcję w funkcji, funkcje wewnętrzne są dostępne tylko w zakresie, w którym zostały zadeklarowane, lub w twoim przypadku pad2można je wywołać tylko w dmyzakresie.

Wszystkie istniejące zmienne dmysą widoczne w pad2, ale nie dzieje się na odwrót: D


2

Posiadanie funkcji wewnątrz funkcji jest całkowicie normalne w JavaScript (i wielu językach).

Poświęć trochę czasu na naukę języka, nie używaj go, ponieważ jest podobny do tego, co już znasz. Proponuję obejrzeć serię prezentacji YUI Douglasa Crockforda na temat Javascript, ze szczególnym uwzględnieniem Act III: Function the Ultimate (link do pobrania wideo, slajdów i transkrypcji)


0

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

Wystąpi błąd. Ponieważ barjest zdefiniowany wewnątrz foo, barbędzie dostępny tylko w środku foo.
Aby go użyć bar, musisz uruchomić go w środku foo.

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.