Pergunta

Fiz uma pergunta sobre Currying e os fechamentos foram mencionados.O que é um fechamento?Como isso se relaciona com o curry?

Foi útil?

Solução

Escopo variável

Quando você declara uma variável local, essa variável tem um escopo.Geralmente, as variáveis ​​locais existem apenas dentro do bloco ou função em que você as declara.

function() {
  var a = 1;
  console.log(a); // works
}    
console.log(a); // fails

Se eu tentar acessar uma variável local, a maioria dos idiomas a procurará no escopo atual e, em seguida, subirá pelos escopos pai até atingir o escopo raiz.

var a = 1;
function() {
  console.log(a); // works
}    
console.log(a); // works

Quando um bloco ou função é concluído, suas variáveis ​​locais não são mais necessárias e geralmente ficam sem memória.

É assim que normalmente esperamos que as coisas funcionem.

Um fechamento é um escopo de variável local persistente

Um encerramento é um escopo persistente que mantém variáveis ​​locais mesmo após a execução do código ter saído desse bloco.Linguagens que suportam encerramento (como JavaScript, Swift e Ruby) permitirão que você mantenha uma referência a um escopo (incluindo seus escopos pais), mesmo após o bloco no qual essas variáveis ​​foram declaradas ter terminado a execução, desde que você mantenha uma referência para aquele bloco ou função em algum lugar.

O objeto de escopo e todas as suas variáveis ​​locais estão vinculadas à função e persistirão enquanto a função persistir.

Isso nos dá portabilidade de função.Podemos esperar que quaisquer variáveis ​​que estavam no escopo quando a função foi definida pela primeira vez ainda estejam no escopo quando chamarmos a função posteriormente, mesmo se chamarmos a função em um contexto completamente diferente.

Por exemplo

Aqui está um exemplo muito simples em JavaScript que ilustra o ponto:

outer = function() {
  var a = 1;
  var inner = function() {
    console.log(a);
  }
  return inner; // this returns a function
}

var fnc = outer(); // execute outer to get inner 
fnc();

Aqui eu defini uma função dentro de uma função.A função interna ganha acesso a todas as variáveis ​​locais da função externa, incluindo a.A variável a está no escopo da função interna.

Normalmente, quando uma função é encerrada, todas as suas variáveis ​​locais são eliminadas.No entanto, se retornarmos a função interna e atribuí-la a uma variável fnc para que persista depois outer saiu, todas as variáveis ​​que estavam no escopo quando inner foi definido também persistir.A variável a foi fechado - está dentro de um fechamento.

Observe que a variável a é totalmente privado para fnc.Esta é uma forma de criar variáveis ​​privadas em uma linguagem de programação funcional como JavaScript.

Como você pode imaginar, quando eu ligo fnc() ele imprime o valor de a, que é "1".

Em uma linguagem sem fechamento, a variável a teria sido coletado como lixo e jogado fora quando a função outer saiu.Chamar fnc geraria um erro porque a não existe mais.

Em JavaScript, a variável a persiste porque o escopo da variável é criado quando a função é declarada pela primeira vez e persiste enquanto a função continuar a existir.

a pertence ao âmbito outer.O escopo de inner tem um ponteiro pai para o escopo de outer. fnc é uma variável que aponta para inner. a persiste enquanto fnc persiste. a está dentro do fechamento.

Outras dicas

Vou dar um exemplo (em JavaScript):

function makeCounter () {
  var count = 0;
  return function () {
    count += 1;
    return count;
  }
}

var x = makeCounter();

x(); returns 1

x(); returns 2

...etc...

O que esta função, makeCounter, faz é retornar uma função, que chamamos de x, que contará um a cada vez que for chamada.Como não estamos fornecendo nenhum parâmetro para x ele deve de alguma forma lembrar a contagem.Ele sabe onde encontrá-lo com base no que é chamado de escopo léxico - ele deve procurar o local onde está definido para encontrar o valor.Esse valor "oculto" é chamado de fechamento.

Aqui está meu exemplo de curry novamente:

function add (a) {
  return function (b) {
    return a + b;
  }
}

var add3 = add(3);

add3(4); returns 7

O que você pode ver é que quando você chama add com o parâmetro a (que é 3), esse valor está contido no encerramento da função retornada que estamos definindo como add3.Dessa forma, quando chamamos add3 ele sabe onde encontrar o valor a para realizar a adição.

A resposta de Kyle é muito bom.Acho que o único esclarecimento adicional é que o encerramento é basicamente um instantâneo da pilha no momento em que a função lambda é criada.Então, quando a função é executada novamente, a pilha é restaurada para esse estado antes de executar a função.Assim, como Kyle menciona, esse valor oculto (count) está disponível quando a função lambda é executada.

Em primeiro lugar, ao contrário do que a maioria das pessoas aqui diz, fechamento é não uma função!E daí é isto?
É um definir de símbolos definidos no "contexto circundante" de uma função (conhecido como seu ambiente) que a tornam uma expressão CLOSED (ou seja, uma expressão na qual cada símbolo é definido e tem um valor, para que possa ser avaliado).

Por exemplo, quando você tem uma função JavaScript:

function closed(x) {
  return x + 3;
}

é um expressão fechada porque todos os símbolos que ocorrem nele estão definidos nele (seus significados são claros), para que você possa avaliá-lo.Em outras palavras, é independente.

Mas se você tiver uma função como esta:

function open(x) {
  return x*y + 3;
}

é um expressão aberta porque há símbolos nele que não foram definidos nele.Nomeadamente, y.Ao olhar para esta função, não podemos dizer o que y é e o que significa, não sabemos o seu valor, portanto não podemos avaliar esta expressão.Ou sejanão podemos chamar esta função até dizermos o que y deveria significar nele.Esse y é chamado de variável livre.

Esse y implora por uma definição, mas esta definição não faz parte da função – ela é definida em algum outro lugar, em seu “contexto circundante” (também conhecido como ambiente).Pelo menos é isso que esperamos :P

Por exemplo, poderia ser definido globalmente:

var y = 7;

function open(x) {
  return x*y + 3;
}

Ou pode ser definido em uma função que o envolve:

var global = 2;

function wrapper(y) {
   var w = "unused";

   return function(x) {
     return x*y + 3;
   }

}

A parte do ambiente que dá às variáveis ​​livres em uma expressão seus significados é a fecho.É chamado assim porque transforma um abrir expressão em um fechado um, fornecendo essas definições ausentes para todos os seus variáveis ​​livres, para que possamos avaliá-lo.

No exemplo acima, a função interna (à qual não demos nome porque não precisávamos) é uma expressão aberta porque a variável y nele está livre – sua definição está fora da função, na função que a envolve.O ambiente para essa função anônima é o conjunto de variáveis:

{
  global: 2,
  w: "unused",
  y: [whatever has been passed to that wrapper function as its parameter `y`]
}

Agora o fecho é aquela parte deste ambiente que fecha a função interna, fornecendo as definições para todos os seus variáveis ​​livres.No nosso caso, a única variável livre na função interna foi y, então o fechamento dessa função é este subconjunto de seu ambiente:

{
  y: [whatever has been passed to that wrapper function as its parameter `y`]
}

Os outros dois símbolos definidos no ambiente são não parte de fecho dessa função, porque não exige que eles sejam executados.Eles não são necessários para fechar isto.

Mais sobre a teoria por trás disso aqui:https://stackoverflow.com/a/36878651/434562

É importante notar que no exemplo acima, a função wrapper retorna sua função interna como um valor.O momento em que chamamos esta função pode ser remoto no tempo a partir do momento em que a função foi definida (ou criada).Em particular, sua função de empacotamento não está mais em execução e seus parâmetros que estavam na pilha de chamadas não estão mais lá:P Isso é um problema, porque a função interna precisa y estar presente quando for chamado!Em outras palavras, exige que as variáveis ​​do seu fechamento sejam de alguma forma sobreviver a função wrapper e estará presente quando necessário.Portanto, a função interna tem que fazer um instantâneo dessas variáveis ​​​​que fazem seu fechamento e as armazenam em algum lugar seguro para uso posterior.(Em algum lugar fora da pilha de chamadas.)

E é por isso que as pessoas muitas vezes confundem o termo fecho ser aquele tipo especial de função que pode fazer instantâneos das variáveis ​​externas que eles usam, ou da estrutura de dados usada para armazenar essas variáveis ​​para mais tarde.Mas espero que você entenda agora que eles são não o fechamento em si - são apenas maneiras de implemento fechamentos em uma linguagem de programação ou mecanismos de linguagem que permitem que as variáveis ​​​​do fechamento da função estejam presentes quando necessário.Existem muitos equívocos em torno dos encerramentos que (desnecessariamente) tornam este assunto muito mais confuso e complicado do que realmente é.

Um encerramento é uma função que pode referenciar o estado em outra função.Por exemplo, em Python, isso usa o fechamento “inner”:

def outer (a):
    b = "variable in outer()"
    def inner (c):
        print a, b, c
    return inner

# Now the return value from outer() can be saved for later
func = outer ("test")
func (1) # prints "test variable in outer() 1

Para ajudar a facilitar a compreensão dos encerramentos, pode ser útil examinar como eles podem ser implementados numa linguagem processual.Esta explicação seguirá uma implementação simplista de encerramentos no Scheme.

Para começar, devo apresentar o conceito de namespace.Quando você insere um comando em um interpretador de Scheme, ele deve avaliar os vários símbolos na expressão e obter seus valores.Exemplo:

(define x 3)

(define y 4)

(+ x y) returns 7

As expressões definem armazenam o valor 3 no ponto para x e o valor 4 no ponto para y.Então, quando chamamos (+ x y), o interpretador procura os valores no namespace e consegue realizar a operação e retornar 7.

No entanto, no Scheme existem expressões que permitem substituir temporariamente o valor de um símbolo.Aqui está um exemplo:

(define x 3)

(define y 4)

(let ((x 5))
   (+ x y)) returns 9

x returns 3

O que a palavra-chave let faz é introduzir um novo namespace com x como valor 5.Você notará que ainda é possível ver que y é 4, fazendo com que a soma seja 9.Você também pode ver que, uma vez que a expressão termina, x volta a ser 3.Neste sentido, x foi temporariamente mascarado pelo valor local.

As linguagens processuais e orientadas a objetos têm um conceito semelhante.Sempre que você declara uma variável em uma função que tem o mesmo nome de uma variável global, você obtém o mesmo efeito.

Como implementaríamos isso?Uma maneira simples é com uma lista vinculada - o cabeçalho contém o novo valor e o final contém o namespace antigo.Quando você precisa procurar um símbolo, comece pela cabeça e desça pela cauda.

Agora vamos passar para a implementação de funções de primeira classe por enquanto.Mais ou menos, uma função é um conjunto de instruções a serem executadas quando a função é chamada culminando no valor de retorno.Quando lemos uma função, podemos armazenar essas instruções nos bastidores e executá-las quando a função for chamada.

(define x 3)

(define (plus-x y)
  (+ x y))

(let ((x 5))
  (plus-x 4)) returns ?

Definimos x como 3 e mais-x como seu parâmetro, y, mais o valor de x.Finalmente chamamos plus-x em um ambiente onde x foi mascarado por um novo x, este com valor 5.Se apenas armazenarmos a operação (+ x y), para a função mais-x, como estamos no contexto de x sendo 5, o resultado retornado seria 9.Isso é chamado de escopo dinâmico.

No entanto, Scheme, Common Lisp e muitas outras linguagens possuem o que é chamado de escopo léxico - além de armazenar a operação (+ x y), também armazenamos o namespace naquele ponto específico.Dessa forma, quando procuramos os valores podemos ver que x, neste contexto, é realmente 3.Isto é um encerramento.

(define x 3)

(define (plus-x y)
  (+ x y))

(let ((x 5))
  (plus-x 4)) returns 7

Em resumo, podemos usar uma lista vinculada para armazenar o estado do namespace no momento da definição da função, permitindo-nos acessar variáveis ​​de escopos delimitadores, além de nos fornecer a capacidade de mascarar localmente uma variável sem afetar o resto do programa.

Aqui está um exemplo do mundo real de por que os fechamentos são arrasadores...Isso saiu direto do meu código Javascript.Deixe-me ilustrar.

Function.prototype.delay = function(ms /*[, arg...]*/) {
  var fn = this,
      args = Array.prototype.slice.call(arguments, 1);

  return window.setTimeout(function() {
      return fn.apply(fn, args);
  }, ms);
};

E aqui está como você o usaria:

var startPlayback = function(track) {
  Player.play(track);  
};
startPlayback(someTrack);

Agora imagine que você deseja que a reprodução comece atrasada, como, por exemplo, 5 segundos depois da execução deste trecho de código.Bem, isso é fácil com delay e é o encerramento:

startPlayback.delay(5000, someTrack);
// Keep going, do other things

Quando Você ligar delay com 5000ms, o primeiro trecho é executado e armazena os argumentos passados ​​em seu encerramento.Então, 5 segundos depois, quando o setTimeout callback acontece, o encerramento ainda mantém essas variáveis, para que possa chamar a função original com os parâmetros originais.
Este é um tipo de curry ou decoração funcional.

Sem fechamentos, você teria que de alguma forma manter o estado dessas variáveis ​​fora da função, espalhando assim o código fora da função com algo que logicamente pertence a ela.O uso de encerramentos pode melhorar muito a qualidade e a legibilidade do seu código.

dr.

Um encerramento é uma função e seu escopo atribuído a (ou usado como) uma variável.Assim, o fechamento do nome:o escopo e a função são incluídos e usados ​​como qualquer outra entidade.

Explicação detalhada no estilo da Wikipedia

De acordo com a Wikipedia, um fechamento é:

Técnicas para implementar vinculação de nomes com escopo lexical em linguagens com funções de primeira classe.

O que isso significa?Vejamos algumas definições.

Explicarei os encerramentos e outras definições relacionadas usando este exemplo:

function startAt(x) {
    return function (y) {
        return x + y;
    }
}

var closure1 = startAt(1);
var closure2 = startAt(5);

console.log(closure1(3)); // 4 (x == 1, y == 3)
console.log(closure2(3)); // 8 (x == 5, y == 3)

Funções de primeira classe

Basicamente isso significa podemos usar funções como qualquer outra entidade.Podemos modificá-los, passá-los como argumentos, retorná-los de funções ou atribuí-los a variáveis.Tecnicamente falando, eles são cidadãos de primeira classe, daí o nome:funções de primeira classe.

No exemplo acima, startAt retorna um (anônimo) função à qual a função é atribuída closure1 e closure2.Como você pode ver, o JavaScript trata as funções como qualquer outra entidade (cidadãos de primeira classe).

Vinculação de nome

Vinculação de nome é sobre descobrir quais dados são uma variável (identificador) referências.O escopo é muito importante aqui, pois é isso que determinará como uma ligação será resolvida.

No exemplo acima:

  • No escopo da função anônima interna, y é obrigado a 3.
  • Em startAtescopo, x é obrigado a 1 ou 5 (dependendo do fechamento).

Dentro do escopo da função anônima, x não está vinculado a nenhum valor, portanto precisa ser resolvido em uma posição superior (startAt's) escopo.

Escopo lexical

Como Wikipédia diz, O escopo:

É a região de um programa de computador onde a ligação é válida: onde o nome pode ser usado para se referir à entidade.

Existem duas técnicas:

  • Escopo léxico (estático):A definição de uma variável é resolvida pesquisando o bloco ou função que a contém e, se isso falhar, pesquisando o bloco externo que a contém e assim por diante.
  • Escopo dinâmico:A função de chamada é pesquisada, depois a função que chamou essa função de chamada e assim por diante, progredindo na pilha de chamadas.

Para mais explicações, confira esta pergunta e dê uma olhada na Wikipédia.

No exemplo acima, podemos ver que o JavaScript tem escopo léxico, porque quando x é resolvido, a ligação é pesquisada na parte superior (startAt's), baseado no código fonte (a função anônima que procura por x é definida dentro startAt) e não com base na pilha de chamadas, na forma (o escopo onde) a função foi chamada.

Concluindo (fechando)

Em nosso exemplo, quando chamamos startAt, ele retornará uma função (de primeira classe) que será atribuída a closure1 e closure2 assim, um fechamento é criado, porque as variáveis ​​passadas 1 e 5 será salvo dentro startAtdo escopo, que será incluído na função anônima retornada.Quando chamamos esta função anônima via closure1 e closure2 com o mesmo argumento (3), o valor de y será encontrado imediatamente (já que esse é o parâmetro dessa função), mas x não está vinculado ao escopo da função anônima, então a resolução continua no escopo da função superior (lexicamente) (que foi salvo no fechamento) onde x é considerado vinculado a qualquer 1 ou 5.Agora sabemos tudo sobre o somatório para que o resultado possa ser retornado e depois impresso.

Agora você deve entender os encerramentos e como eles se comportam, o que é uma parte fundamental do JavaScript.

Escovando

Ah, e você também aprendeu o que escovando é sobre:você usa funções (fechamento) para passar cada argumento de uma operação em vez de usar uma função com vários parâmetros.

Funções que não contêm variáveis ​​livres são chamadas de funções puras.

Funções que contêm uma ou mais variáveis ​​livres são chamadas de encerramentos.

var pure = function pure(x){
  return x 
  // only own environment is used
}

var foo = "bar"

var closure = function closure(){
  return foo 
  // foo is a free variable from the outer environment
}

fonte: https://leanpub.com/javascriptallongesix/read#leanpub-auto-if-functions-without-free-variables-are-pure-are-closures-impure

Em uma situação normal, as variáveis ​​são vinculadas pela regra de escopo:Variáveis ​​locais funcionam apenas dentro da função definida.O fechamento é uma forma de quebrar essa regra temporariamente por conveniência.

def n_times(a_thing)
  return lambda{|n| a_thing * n}
end

no código acima, lambda(|n| a_thing * n} é o fechamento porque a_thing é referido pelo lambda (um criador de função anônima).

Agora, se você colocar a função anônima resultante em uma variável de função.

foo = n_times(4)

foo quebrará a regra normal de escopo e começará a usar 4 internamente.

foo.call(3)

retorna 12.

Resumindo, o ponteiro de função é apenas um ponteiro para um local na base do código do programa (como o contador do programa).Enquanto Fechamento = ponteiro de função + quadro de pilha.

.

Fecho é um recurso em JavaScript onde uma função tem acesso às suas próprias variáveis ​​de escopo, acesso às variáveis ​​externas da função e acesso às variáveis ​​globais.

O encerramento tem acesso ao escopo da função externa mesmo após o retorno da função externa.Isso significa que um encerramento pode lembrar e acessar variáveis ​​e argumentos de sua função externa mesmo após a conclusão da função.

A função interna pode acessar as variáveis ​​definidas em seu próprio escopo, no escopo da função externa e no escopo global.E a função externa pode acessar a variável definida em seu próprio escopo e no escopo global.

******************
Example of Closure
******************

var globalValue = 5;

function functOuter() 
{
    var outerFunctionValue = 10;

    //Inner function has access to the outer function value
    //and the global variables
    function functInner() 
    {
        var innerFunctionValue = 5;
        alert(globalValue+outerFunctionValue + innerFunctionValue);
    }
    functInner();
}
functOuter();

A saída será 20, que soma a variável própria da função interna, a variável da função externa e o valor da variável global.

Aqui está outro exemplo da vida real, usando uma linguagem de script popular em jogos - Lua.Eu precisava mudar um pouco a forma como uma função de biblioteca funcionava para evitar um problema com a indisponibilidade do stdin.

local old_dofile = dofile

function dofile( filename )
  if filename == nil then
    error( 'Can not use default of stdin.' )
  end

  old_dofile( filename )
end

O valor de old_dofile desaparece quando este bloco de código termina seu escopo (porque é local), porém o valor foi colocado em um encerramento, então a nova função dofile redefinida PODE acessá-lo, ou melhor, uma cópia armazenada junto com a função como um 'valor superior'.

De Lua.org:

Quando uma função é escrita dentro de outra função, ela tem acesso total às variáveis ​​locais da função envolvente;esse recurso é chamado de escopo lexical.Embora isso possa parecer óbvio, não é.O escopo léxico, somado às funções de primeira classe, é um conceito poderoso em uma linguagem de programação, mas poucas linguagens suportam esse conceito.

Se você pertence ao mundo Java, pode comparar um encerramento com uma função membro de uma classe.Veja este exemplo

var f=function(){
  var a=7;
  var g=function(){
    return a;
  }
  return g;
}

A função g é um fechamento: g fecha a em.Então g pode ser comparado com uma função membro, a pode ser comparado com um campo de classe, e a função f com uma aula.

Fechamentos sempre que temos uma função definida dentro de outra função, a função interna tem acesso às variáveis ​​declaradas na função externa.Os fechamentos são melhor explicados com exemplos.Na Listagem 2-18, você pode ver que a função interna tem acesso a uma variável (variableInouterfunção) do escopo externo.As variáveis ​​na função externa foram fechadas (ou vinculadas) pela função interna.Daí o termo fechamento.O conceito em si é bastante simples e bastante intuitivo.

Listing 2-18:
    function outerFunction(arg) {
     var variableInOuterFunction = arg;

     function bar() {
             console.log(variableInOuterFunction); // Access a variable from the outer scope
     }
     // Call the local function to demonstrate that it has access to arg
     bar(); 
    }
    outerFunction('hello closure!'); // logs hello closure!

fonte: http://index-of.es/Varios/Basarat%20Ali%20Syed%20(auth.)-Beginning%20Node.js-Apress%20(2014).pdf

Por favor, dê uma olhada no código abaixo para entender o fechamento mais profundamente:

        for(var i=0; i< 5; i++){            
            setTimeout(function(){
                console.log(i);
            }, 1000);                        
        }

Aqui o que será produzido? 0,1,2,3,4 não será isso 5,5,5,5,5 por causa do fechamento

Então, como isso vai resolver?A resposta está abaixo:

       for(var i=0; i< 5; i++){
           (function(j){     //using IIFE           
                setTimeout(function(){
                               console.log(j);
                           },1000);
            })(i);          
        }

Deixe-me explicar de forma simples, quando uma função criada, nada acontece até que ela chame o loop for no primeiro código chamado 5 vezes, mas não chamado imediatamente, então quando é chamado, ou seja, após 1 segundo e também é assíncrono, antes que o loop for termine e armazene o valor 5 em var i e finalmente execute setTimeout funcionar cinco vezes e imprimir 5,5,5,5,5

Aqui está como resolver usando IIFE, ou seja, Expressão de Função de Invocação Imediata

       (function(j){  //i is passed here           
            setTimeout(function(){
                           console.log(j);
                       },1000);
        })(i);  //look here it called immediate that is store i=0 for 1st loop, i=1 for 2nd loop, and so on and print 0,1,2,3,4

Para saber mais, entenda o contexto de execução para entender o fechamento.

  • Existe mais uma solução para resolver isso usando let (recurso ES6), mas nos bastidores a função acima é trabalhada

     for(let i=0; i< 5; i++){           
         setTimeout(function(){
                        console.log(i);
                    },1000);                        
     }
    
    Output: 0,1,2,3,4
    

=> Mais explicações:

Na memória, quando o loop for executar a imagem, faça como abaixo:

Ciclo 1)

     setTimeout(function(){
                    console.log(i);
                },1000);  

Ciclo 2)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Ciclo 3)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Ciclo 4)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Ciclo 5)

     setTimeout(function(){
                    console.log(i);
                },1000);  

Aqui i não é executado e depois do loop completo, var i armazenou o valor 5 na memória, mas seu escopo está sempre visível em sua função filha, então quando a função é executada dentro setTimeout cinco vezes ele imprime 5,5,5,5,5

então, para resolver isso, use IIFE conforme explicado acima.

Escovando :Ele permite avaliar parcialmente uma função passando apenas um subconjunto de seus argumentos.Considere isto:

function multiply (x, y) {
  return x * y;
}

const double = multiply.bind(null, 2);

const eight = double(4);

eight == 8;

Fecho:Um encerramento nada mais é do que acessar uma variável fora do escopo de uma função.É importante lembrar que uma função dentro de uma função ou função aninhada não é um fechamento.Closures são sempre usados ​​quando é necessário acessar variáveis ​​fora do escopo da função.

function apple(x){
   function google(y,z) {
    console.log(x*y);
   }
   google(7,2);
}

apple(3);

// the answer here will be 21

O fechamento é muito fácil.Podemos considerá-lo da seguinte forma:Fechamento = função + seu ambiente lexical

Considere a seguinte função:

function init() {
    var name = “Mozilla”;
}

Qual será o fechamento no caso acima?Função init() e variáveis ​​em seu ambiente léxico, ou seja, nome.Fecho =inicial() + nome

Considere outra função:

function init() {
    var name = “Mozilla”;
    function displayName(){
        alert(name);
}
displayName();
}

Quais serão os fechamentos aqui?A função interna pode acessar variáveis ​​da função externa.displayName() pode acessar o nome da variável declarada na função pai, init().No entanto, as mesmas variáveis ​​locais em displayName() serão usadas se existirem.

Encerramento 1: função init + (variável de nome + função displayName()) -> escopo léxico

Encerramento 2: função displayName + (variável de nome) -> escopo léxico

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top