Funzione annidata JavaScript


96

Ho un pezzo di codice per javascript che semplicemente non capisco:

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

Come si può definire una funzione all'interno di un'altra funzione? Possiamo chiamare pad2 () dall'esterno della funzione my ()?

Per favore accendi un po 'di luce. Grazie


13
le funzioni possono essere create all'interno delle funzioni. Questo è perfettamente valido.
0x499602D2

Risposte:


140

Le funzioni sono un altro tipo di variabile in JavaScript (con alcune sfumature ovviamente). La creazione di una funzione all'interno di un'altra funzione cambia l'ambito della funzione nello stesso modo in cui cambierebbe l'ambito di una variabile. Ciò è particolarmente importante per l'uso con le chiusure per ridurre l'inquinamento globale dello spazio dei nomi.

Le funzioni definite all'interno di un'altra funzione non saranno accessibili all'esterno della funzione a meno che non siano state associate a un oggetto accessibile all'esterno della funzione:

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

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

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

In questo esempio, la funzione baz sarà disponibile per l'uso dopo che la foofunzione è stata eseguita, poiché è sovrascritta window.baz. La funzione bar non sarà disponibile in nessun contesto diverso dagli ambiti contenuti all'interno della foofunzione.

come esempio diverso:

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

La Fizzfunzione è progettata come un costruttore in modo che, quando viene eseguita, assegni una buzzfunzione all'oggetto appena creato.


Cos'è window.baz = baz? Perché questa linea m? Ke baz è disponibile?
Ziyang Zhang

@ZiyangZhang, il paragrafo dopo quel blocco di codice ha la spiegazione, c'era una parte particolare che non è chiara?
zzzzBov

35

Si chiama chiusura .

Fondamentalmente, la funzione definita all'interno di un'altra funzione è accessibile solo all'interno di questa funzione. Ma può essere passato come risultato e quindi questo risultato può essere chiamato.

È una caratteristica molto potente. Puoi vedere ulteriori spiegazioni qui:

javascript_closures_for_dummies.html mirror su Archive.org


13
function x() {}

è equivalente (o molto simile) a

var x = function() {}

a meno che non mi sbagli.

Quindi non c'è niente di divertente in corso.


8
La prima sintassi verrà spostata all'inizio del documento. quindi è possibile chiamare la funzione 'x' prima che la funzione sia inizializzata.
Tom

10
La prima sintassi ti darà anche tracce di stack molto più belle con funzioni con nome, la seconda ti darà un mal di testa
TheZ

@TheZ Penso che Chrome abbia recentemente aggiunto l'inferenza del nome della funzione al debug in modo da non avere lo stesso mal di testa di prima nel caso comune.
jinglesthula

@jinglesthula Sì! Chrome ha aggiunto questa deduzione del nome qualche tempo fa ed è molto apprezzata :)
TheZ

10

La creazione di istanze di funzioni è consentita all'interno e all'esterno delle funzioni. All'interno di queste funzioni, proprio come le variabili, le funzioni annidate sono locali e quindi non possono essere ottenute dall'ambito esterno.

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

foomanipola bardentro di sé. barnon può essere toccato dall'ambito esterno a meno che non sia definito nell'ambito esterno.

Quindi questo non funzionerà:

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

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

4

Quando dichiari una funzione all'interno di una funzione, le funzioni interne sono disponibili solo nell'ambito in cui sono dichiarate o, nel tuo caso, pad2possono essere chiamate solo dmynell'ambito.

Tutte le variabili esistenti in dmysono visibili in pad2, ma non avviene il contrario: D


2

È perfettamente normale in Javascript (e in molti linguaggi) avere funzioni all'interno di funzioni.

Prenditi il ​​tempo per imparare la lingua, non usarla perché è simile a ciò che già conosci. Suggerirei di guardare la serie di presentazioni YUI di Douglas Crockford su Javascript, con particolare attenzione all'Atto III: Function the Ultimate (link al download del video, diapositive e trascrizione)


0

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

Genererà un errore. Poiché barè definito all'interno foo, barsarà accessibile solo all'interno foo.
Per usarlo barè necessario eseguirlo all'interno foo.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.