Função aninhada de JavaScript

96

Recebi um pedaço de código para javascript que simplesmente não entendo:

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

Como uma função pode ser definida dentro de outra função? Podemos chamar pad2 () de fora da minha função ()?

Por favor, coloque alguma luz sobre isso. obrigado

Thomas
fonte
13
funções podem ser criadas dentro de funções. Isso é perfeitamente válido.
0x499602D2

Respostas:

140

Funções são outro tipo de variável em JavaScript (com algumas nuances, é claro). Criar uma função dentro de outra função muda o escopo da função da mesma forma que mudaria o escopo de uma variável. Isso é especialmente importante para uso com encerramentos para reduzir a poluição total do namespace global.

As funções definidas em outra função não estarão acessíveis fora da função, a menos que tenham sido anexadas a um objeto acessível fora da função:

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

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

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

Neste exemplo, a função baz estará disponível para uso depois que a foofunção for executada, uma vez que é substituída window.baz. A função bar não estará disponível para qualquer contexto diferente dos escopos contidos na foofunção.

como um exemplo diferente:

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

A Fizzfunção é projetada como um construtor para que, quando executada, atribua uma buzzfunção ao objeto recém-criado.

zzzzBov
fonte
O que é window.baz = baz? Por que esta linha m? Ke baz está disponível?
Ziyang Zhang
@ZiyangZhang, o parágrafo após aquele bloco de código tem a explicação, havia uma parte específica que não está clara?
zzzzBov
35

É chamado de fechamento .

Basicamente, a função definida em outra função está acessível apenas dentro desta função. Mas pode ser passado como resultado e esse resultado pode ser chamado.

É um recurso muito poderoso. Você pode ver mais explicações aqui:

javascript_closures_for_dummies.html espelho em Archive.org

Tadeck
fonte
13
function x() {}

é equivalente (ou muito semelhante) a

var x = function() {}

a menos que eu esteja enganado.

Portanto, não há nada de engraçado acontecendo.

Andreas
fonte
8
A primeira sintaxe será movida para o início do documento. portanto, é possível chamar a função 'x' antes que a função seja inicializada.
Tom
10
A primeira sintaxe também fornecerá rastreamentos de pilha muito mais agradáveis ​​com funções nomeadas, a segunda lhe dará uma dor de cabeça
TheZ
@TheZ Acho que o Chrome adicionou recentemente a inferência de nome de função à depuração para que você não tenha a mesma dor de cabeça que antes no caso comum.
jinglesthula
@jinglesthula Sim! O Chrome adicionou essa inferência de nome há um tempo e é muito apreciado :)
TheZ
10

A instanciação de funções é permitida dentro e fora das funções. Dentro dessas funções, assim como as variáveis, as funções aninhadas são locais e, portanto, não podem ser obtidas do escopo externo.

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

foomanipula bardentro de si. barnão pode ser tocado a partir do escopo externo, a menos que seja definido no escopo externo.

Então, isso não vai funcionar:

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

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

Quando você declara uma função dentro de uma função, as funções internas estão disponíveis apenas no escopo em que foram declaradas ou, no seu caso, pad2só podem ser chamadas no dmyescopo.

Todas as variáveis ​​existentes em dmysão visíveis em pad2, mas não acontece o contrário: D

pedrochaves
fonte
2

É perfeitamente normal em Javascript (e em muitas linguagens) ter funções dentro de funções.

Reserve um tempo para aprender o idioma, não o use porque é semelhante ao que você já conhece. Eu sugiro assistir a série de apresentações YUI de Douglas Crockford em Javascript, com foco especial no Ato III: Funcionalizar o Ultimate (link para download de vídeo, slides e transcrição)

Joaquim rendeiro
fonte
0

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

Irá gerar um erro. Uma vez que barestá definido dentro foo, barsó estará acessível dentro foo.
Para usar barvocê precisa executá-lo dentro foo.

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

Justin Liu
fonte