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


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.


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


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.


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

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


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)


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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.