Como os bloqueadores de javascript funcionam?

Como você explicaria o fechamento do JavaScript para alguém que tem conhecimento dos conceitos de que eles são compostos (por exemplo, funções, variáveis, etc.), mas não entende os encerramentos em si?

Eu vi um exemplo do esquema dado na Wikipedia, mas, infelizmente, isso não ajudou.

7654
21 сент. definido como e-satis em 21 de setembro 2008-09-21 17:12 '08 em 5:12 pm 2008-09-21 17:12
@ 89 respostas
  • 1
  • 2
  • 3

Fechando o javascript para iniciantes

Enviado por Morris em Tue, 2006-02-21 10:19. A comunidade foi editada desde então.

Fechar não é mágica

Esta página explica o fechamento para que o programador possa entendê-los - usando o código JavaScript em funcionamento. Isto não é para gurus ou programadores funcionais.

O fechamento não é difícil de entender assim que o conceito básico é costurado. No entanto, eles não podem ser entendidos lendo explicações teóricas ou acadêmicas!

Este artigo é destinado a programadores com alguma experiência básica de programação e pode ler a seguinte função JavaScript:

recursos de primeira classe ;  é uma expressão que pode se referir a variáveis ​​dentro de seu escopo (quando foi declarada anteriormente), ser atribuída a uma variável, passada como um argumento de função ou retornada como resultado de uma função. 

Exemplo de encerramento

O código a seguir retorna uma referência de função:

Exemplo 4

Todas as três funções globais têm uma referência comum para o mesmo fechamento, porque todas elas são declaradas durante uma única chamada para setupSomeGlobals() .

 function sayAlice() { var say = function() { console.log(alice); } // Local variable that ends up within closure var alice = 'Hello Alice'; return say; } sayAlice()();// logs "Hello Alice" 

Tricky: também note, say variável say também esteja dentro do closure, e ele pode sayAlice() qualquer outra função que possa ser declarada em sayAlice() , ou que possa ser obtida recursivamente dentro de uma função interna.

Exemplo 6

Esta é uma verdadeira magia para todas as pessoas, então você precisa entender isso. Tenha muito cuidado se você definir uma função dentro de um loop: variáveis ​​locais do fechamento podem não agir como você pode pensar primeiro.

Você precisa entender a função "levantamento de variáveis" do javascript para entender este exemplo.

 function newClosure(someNum, someRef) { // Local variables that end up within closure var num = someNum; var anArray = [1,2,3]; var ref = someRef; return function(x) { num += x; anArray.push(num); console.log('num: ' + num + '; anArray: ' + anArray.toString() + '; ref.someVar: ' + ref.someVar + ';'); } } obj = {someVar: 4}; fn1 = newClosure(4, obj); fn2 = newClosure(5, obj); fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4; fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4; obj.someVar++; fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5; fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5; 

Resumo

Se tudo parece completamente obscuro, é melhor brincar com exemplos. Ler explicações é muito mais difícil do que entender exemplos. Minhas explicações para fechamentos e quadros de pilha, etc. Eles não são tecnicamente corretos - são simples simplificações projetadas para ajudar a entender. Depois que a ideia básica for resolvida, você pode obter os detalhes mais tarde.

Pontos finais:

  • Sempre que você usa a function dentro de outra função, o fechamento é usado.
  • Sempre que você usa eval() dentro de uma função, um fechamento é usado. Texto que você eval pode se referir a variáveis ​​locais de uma função, e em eval você pode até criar novas variáveis ​​locais com eval('var foo = …')
  • Quando você usa a new Function(…) ( construtor de função ) dentro de uma função, ela não cria um fechamento. (A nova função não pode se referir às variáveis ​​locais da função externa.)
  • Fechar em JavaScript é como manter uma cópia de todas as variáveis ​​locais, exatamente como quando você sai de uma função.
  • É provavelmente melhor pensar que o encerramento é sempre criado como uma entrada de função e as variáveis ​​locais são adicionadas a esse fechamento.
  • Um novo conjunto de variáveis ​​locais é salvo toda vez que uma função é chamada com um fechamento (dado que a função contém uma declaração de função dentro dela, ou a referência a essa função interna é retornada ou a referência externa é armazenada de alguma forma).
  • Duas funções podem parecer como se tivessem o mesmo código-fonte, mas têm um comportamento completamente diferente devido ao seu fechamento oculto. Eu não acho que o código JavaScript pode realmente descobrir se a função tem um fechamento de link ou não.
  • Se você tentar fazer alterações no código-fonte dinâmico (por exemplo: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola')); ), ele não funcionará se myFunction for um fechamento (claro, você você não pensaria em substituir linhas de código-fonte em tempo de execução, mas ...).
  • Você pode obter as declarações de função dentro das declarações de função dentro das funções do mdash, e você pode obter o fechamento em mais de um nível.
  • Eu acho que geralmente o fechamento é um termo tanto para uma função quanto para variáveis ​​capturadas. Por favor, note que eu não uso essa definição neste artigo!
  • Eu suspeito que closures em JavaScript são diferentes daqueles comumente encontrados em linguagens funcionais.

Conexões

obrigado a

Se você acabou de descobrir sobre o fechamento (aqui ou em outro lugar!), Então, estou interessado em qualquer feedback seu sobre quaisquer alterações que você possa sugerir para tornar esse artigo mais claro. Envie uma mensagem para morrisjohns.com (morris_closure @). Por favor, note que eu não sou um guru JavaScript - não no final.


O post original de Morris pode ser encontrado no arquivo da Internet .

6329
21 сент. a resposta é dada por Joel Anair 21 set . 2008-09-21 17:18 '08 at 17:18 2008-09-21 17:18

Sempre que você vê a palavra-chave da função em outra função, a função interna tem acesso às variáveis ​​na função externa.

 function foo(x) { var tmp = 3; return function (y) { console.log(x + y + (++tmp)); // will also log 16 } } var bar = foo(2); // bar is now a closure. bar(10); 

A função acima também irá escrever 16, porque a bar ainda pode se referir a x e tmp , mesmo que não esteja mais dentro da região.

No entanto, como o tmp ainda permanece em torno do fechamento da bar interna, ele também aumenta. Aumentará cada vez que você chamar a bar .

O exemplo mais simples de um fechamento é o seguinte:

border=0

Como esperado, cada chamada para bar(10) irá incrementar x.memb . Você não pode esperar que x simplesmente se refira ao mesmo objeto que a variável age ! Depois de um par de chamadas para bar age.memb haverá 2! Esse link serve como base para vazamentos de memória com objetos HTML.

3825
21 сент. resposta dada a Ali em 21 de setembro 2008-09-21 18:16 '08 at 6:16 pm 2008-09-21 18:16

PREFÁCIO: esta resposta foi escrita quando a questão era:

Como o velho Albert, ele disse: "Se você não pode explicar isso para uma criança de seis anos, você mesmo não entende isso". Bem, eu tentei explicar o fechamento de JS a um amigo de 27 anos e falhei completamente.

Alguém poderia pensar que eu tenho 6 anos e estranhamente interessado neste assunto?

Tenho certeza de que eu era uma daquelas pessoas que tentaram tirar a questão inicial literalmente. Desde então, esta questão foi mutada várias vezes, então minha resposta agora pode parecer incrivelmente estúpida e inapropriada. Espero que a ideia geral desta história seja interessante.


Eu sou um grande fã de analogias e metáforas na explicação de conceitos complexos, então deixe-me tentar minha mão na história.

Era uma vez:

Houve uma princesa ...

 function princess() { 

Ela viveu em um mundo maravilhoso cheio de aventura. Ela conheceu seu príncipe Charles, rodeou seu mundo em um unicórnio, lutou com dragões, encontrou animais falantes e muitas outras coisas fantásticas.

  var adventures = []; function princeCharming() {  } var unicorn = {  }, dragons = [  ], squirrel = "Hello!";  

Mas ela sempre teve que retornar ao seu mundo aborrecido de problemas e adultos.

  return { 

E ela frequentemente dizia a eles sobre sua última incrível aventura como princesa.

  story: function() { return adventures[adventures.length - 1]; } }; } 

Mas tudo o que viram foi uma menininha ...

 var littleGirl = princess(); 

... contando histórias sobre magia e fantasia.

 littleGirl.story(); 

E enquanto os adultos sabiam sobre princesas reais, eles nunca teriam acreditado em unicórnios ou dragões, porque eles nunca os viram. Os adultos disseram que eles existem apenas dentro da imaginação de uma menina.

Mas nós sabemos a verdade verdadeira; que uma garotinha com uma princesa dentro ...

... na verdade uma princesa com uma garotinha dentro.

2273
24 июня '11 в 21:49 2011-06-24 21:49 a resposta é dada por Jacob Swartwood em 24 de junho de 2011 às 21:49 2011-06-24 21:49

Levando essa questão a sério, precisamos descobrir que uma pessoa típica de 6 anos é cognitivamente capaz, embora, reconhecidamente, aqueles que estão interessados ​​em JavaScript não sejam tão típicos.

Sobre o desenvolvimento da infância: dos 5 aos 7 anos diz-se:

Seu filho será capaz de seguir as instruções em duas etapas. Por exemplo, se você disser ao seu filho: "Vá até a cozinha e pegue um saco de lixo", ele pode se lembrar dessa direção.

Podemos usar este exemplo para explicar os encerramentos da seguinte forma:

Uma cozinha é um fechamento em que há uma variável local chamada trashBags . Dentro da cozinha há uma função getTrashBag que recebe um saco de lixo e o devolve.

Podemos codificar isso em javascript da seguinte forma:

696
02 сент. a resposta é dada dlaliberte 02 set . 2011-09-02 18:23 '11 às 18:23 2011-09-02 18:23

Соломенный человек