Función anidada de JavaScript

96

Obtuve un fragmento de código para javascript que simplemente no entiendo:

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

¿Cómo se puede definir una función dentro de otra función? ¿Podemos llamar a pad2 () desde fuera de mi función ()?

Por favor, ponle algo de luz. Gracias

Thomas
fuente
13
las funciones se pueden crear dentro de funciones. Eso es perfectamente válido.
0x499602D2

Respuestas:

140

Las funciones son otro tipo de variable en JavaScript (con algunos matices, por supuesto). La creación de una función dentro de otra función cambia el alcance de la función de la misma manera que cambiaría el alcance de una variable. Esto es especialmente importante para su uso con cierres para reducir la contaminación global total del espacio de nombres.

Las funciones definidas dentro de otra función no serán accesibles fuera de la función a menos que se hayan adjuntado a un objeto que sea accesible fuera de la función:

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

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

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

En este ejemplo, la función baz estará disponible para su uso después de que la foofunción se haya ejecutado, ya que está anulada window.baz. La función de barra no estará disponible para ningún contexto que no sean los ámbitos contenidos en la foofunción.

como un ejemplo diferente:

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

La Fizzfunción está diseñada como un constructor de modo que, cuando se ejecuta, asigna una buzzfunción al objeto recién creado.

zzzzBov
fuente
¿Qué es window.baz = baz? ¿Por qué esta línea m? Ke baz está disponible?
Ziyang Zhang
@ZiyangZhang, el párrafo después de ese bloque de código tiene la explicación, ¿hubo alguna parte en particular que no está clara?
zzzzBov
35

Se llama cierre .

Básicamente, la función definida dentro de otra función es accesible solo dentro de esta función. Pero se puede pasar como resultado y luego se puede llamar a este resultado.

Es una característica muy poderosa. Puedes ver más explicación aquí:

javascript_closures_for_dummies.html espejo en Archive.org

Tadeck
fuente
13
function x() {}

es equivalente (o muy similar) a

var x = function() {}

a menos que me equivoque.

Así que no pasa nada divertido.

Andreas
fuente
8
La primera sintaxis se moverá al inicio del documento. por lo que es posible llamar a la función 'x' antes de que se inicialice la función.
Tom
10
La primera sintaxis también le proporcionará seguimientos de pila mucho más agradables con funciones con nombre, la segunda le dará un dolor de cabeza
TheZ
@TheZ Creo que Chrome agregó recientemente la inferencia del nombre de la función a la depuración para que no tenga el mismo dolor de cabeza que antes en el caso común.
jinglesthula
@jinglesthula ¡Sí! Chrome agregó esta inferencia de nombre hace un tiempo y es muy apreciada :)
TheZ
10

La instanciación de funciones está permitida dentro y fuera de las funciones. Dentro de esas funciones, al igual que las variables, las funciones anidadas son locales y, por lo tanto, no se pueden obtener del ámbito externo.

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

foomanipula bardentro de sí mismo. barno se puede tocar desde el alcance externo a menos que esté definido en el alcance externo.

Entonces esto no funcionará:

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

bar(); // throws error: bar is not defined
0x499602D2
fuente
4

Cuando declaras una función dentro de una función, las funciones internas solo están disponibles en el ámbito en el que están declaradas, o en tu caso, pad2solo se pueden llamar en el dmyámbito.

Todas las variables existentes en dmyson visibles en pad2, pero no sucede al revés: D

pedrochaves
fuente
2

Es perfectamente normal en Javascript (y muchos lenguajes) tener funciones dentro de funciones.

Tómate el tiempo para aprender el idioma, no lo uses sobre la base de que es similar a lo que ya conoces. Sugeriría ver la serie de presentaciones de YUI de Douglas Crockford en Javascript, con especial énfasis en el Acto III: Función lo último (enlace para descarga de video, diapositivas y transcripción)

Joaquim Rendeiro
fuente
0

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

Lanzará un error. Dado que barestá definido por dentro foo, barsolo será accesible por dentro foo.
Para usarlo barnecesitas ejecutarlo adentro foo.

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

Justin Liu
fuente