Compreender o comportamento das variáveis ao Implementando RecursãoCompreensão do comportamento das variáveis quando Implementar Recursividade Problema Você deseja implementar recursão em JavaScript, e você também quiser entender como as variáveis irá se comportar nessas circunstâncias. Teoria em JavaScript, você não precisa declarar o tipo de variável, ou mesmo declarar a variável. Por exemplo, o código a seguir funciona perfeitamente: if (contador == 1) ( buffer = "Contador é 1";) document.getElementById ( "resultado"). InnerHTML = buffer; A variável buffer não foi declarada antes de se bloquear no código anterior. A última linha do código utiliza o buffer de variável para atribuir a propriedade innerHTML. Esse tipo de declaração é problemático porque buffer pode ser indefinido. JavaScript não vou mencionar isso como um erro, e innerHTML será atribuído o valor indefinido. Este exemplo ilustra que as variáveis em JavaScript podem se comportar de maneiras que um programador com um fundo Java ou C # pode não estar acostumado. O foco desta receita está em descobrir como uma variável se comporta em diferentes contextos. Um exemplo é o contexto de implementação da recursão em JavaScript. Solução Duas funções exemplo que implementar recursão em JavaScript seguir. Fonte: / website / ROOT / ajaxrecipes / javascript / variablebehavior.html função RecursionGlobal (contador) (info ( "RecursionGlobal localCounter ()", typeof localCounter ()); localCounter = contador; info ( "RecursionGlobal localCounter ()", localCounter); se (localCounter <3) (RecursionGlobal (localCounter + 1);)) function RecursionLocal (contador) (info ( "RecursionLocal localCounter ()", typeof localCounter ()); var contador localCounter =; info ( "RecursionLocal localCounter ()", localCounter); if (localCounter <3) (RecursionLocal (localCounter + 1);)) O exemplo mostra dois métodos: RecursionGlobal e RecursionLocal. Entre os dois métodos não existe uma única diferença, como mostrado no código a negrito: a palavra-chave var JavaScript. A única palavra-chave var é a variação na forma como a variável localCounter está armazenado. O comportamento de ambos os métodos é idêntico ao executado e gera o mesmo resultado. Você pode pensar à primeira vista que a palavra-chave var não serve qualquer propósito. Mas a palavra-chave var não servir a um propósito, que é ilustrado pela execução o seguinte programa: Info: recursion_global *** Introdução *** Info: RecursionGlobal (localCounter) Info indefinido: RecursionGlobal (1) localCounter Info: RecursionGlobal) (localCounter número Info: RecursionGlobal (2) localCounter Info: RecursionGlobal) (localCounter número Info: RecursionGlobal (localCounter 3) Info: recursion_local *** Introdução *** Info: RecursionLocal (localCounter) Info indefinido: RecursionLocal (1) localCounter Info: RecursionLocal localCounter () Info indefinido: RecursionLocal (2) localCounter Info: RecursionLocal localCounter () Info indefinido: RecursionLocal localCounter (3)
Repare que quando a função RecursionGlobal executado, o tipo de localCounter para a primeira chamada é indefinido e, posteriormente, que é número. Em contraste, quando a função RecurisonLocal é chamado, o tipo de localCounter é indefinido para cada chamada. Isto significa que var serve o propósito de declarar uma variável que é local para o âmbito do qual é declarada. Se a variável não está associada a uma palavra-chave var, então a variável é declarada no escopo global. No caso de criar um laço de recursão, você precisará usar a palavra-chave var para todos os casos, caso contrário, poderia haver corrupção de dados. O exemplo a seguir ilustra como a inverter o conteúdo de uma pilha usando a recursividade. Quando utilizar a recursividade, às vezes você terá que declarar os parâmetros da função que servem para outros fins e não como valores de referência. Fonte: / website / ROOT / ajaxrecipes / javascript / variablebehavior.html função RecursiveStackOldWay (arrayToProcess, processedArray) (info ( "RecursiveStackOldWay", "---> Start "); info (" RecursiveStackOldWay "," profundidade recursiva = "+ (processedArray. length + 1)); processedArray.push (arrayToProcess.pop ()); if (arrayToProcess.length> 0) (RecursiveStackOldWay arrayToProcess (, processedArray);) info ( "RecursiveStackOldWay", "---> End ");) arrayToProcess = new Array (); arrayToProcess.push ( "valor1"); arrayToProcess.push ( "valor2"); processedArray = new Array () RecursiveOldWayStack (arrayToProcess, processedArray); Aqui, a função RecursiveStackOldWay tem dois parâmetros: arrayToProcess e processedArray. O primeiro parâmetro, arrayToProcess, é a matriz que será invertida. O segundo parâmetro, processedArray, é o destino da pilha. O destino da pilha precisa ser arrastado como um parâmetro para cada recursão, para que a função pode colocar a pilha em algum lugar. O chamador é responsável por instanciar o destino pilha e passá-lo para a função recursiva. Muitas vezes, porém, ao criar funções recursivas , você precisará chamar a função com certos parâmetros que são definidos no topo primeira chamada nível. Esses parâmetros não têm nada a ver com a chamada inicial, mas a primeira chamada top-level tem de declará-los (processedArray). Em poucas palavras, o problema é que ao chamar uma função recursiva, você precisa inicializar um conjunto de variáveis que são então usados pela recursividade. No exemplo, a inicialização é uma responsabilidade do chamador. A solução funciona, mas está longe de ser ideal, pois o desenvolvedor precisa para entender como certos parâmetros de função, mesmo que não possa ser utilizado pelo chamador. Outra solução é criar uma função wrapper para a recursão que inicializa os parâmetros e em seguida, chama a recursão. A função wrapper vai funcionar, mas agora o programador tem de manter a função de recursão e da função de mensagens publicitárias. JavaScript oferece uma terceira solução: deixar a função de recursão inicializar sozinho. A pergunta é, como funciona a recursividade sabe que está sendo chamado pela primeira vez? Em uma linguagem de programação tradicional como Java ou C #, um parâmetro booleano seria definido e definido como true para indicar a primeira chamada, e false para indicar qualquer chamada posterior. JavaScript A solução não requer uma bandeira ou um indicador, pois os parâmetros em si são indicadores. Por exemplo, imagine-se a implementação da função RecursiveOldWayStack é e permanece como o código que chama RecursiveOldWayStack assemelha a seguinte: arrayToProcess = new Array (); arrayToProcess.push ( "valor1"); arrayToProcess.push ( "valor2"); processedArray var = RecursiveOldWayStack (arrayToProcess); Na implementação vez, não o chamador é responsável por instanciar o destino pilha. Essa responsabilidade foi delegada a função RecursiveOldWayStack. Entanto, um problema surge porque RecursiveOldWayStack precisa inicializar e começar a recursividade. A solução usada por JavaScript para determinar se o segundo parâmetro é definido, como ilustrado no seguinte função modificada chamada RecursiveStack. Fonte: / website / ROOT / ajaxrecipes / javascript / variablebehavior.html função RecursiveStack (arrayToProcess, processedArray) (info ( "RecursiveStack", "---> Start "); if (typeof (processedArray) == "undefined") ( info ( "RecursiveStack", "inicial"); processedArray = new Array (); RecursiveStack arrayToProcess (, processedArray); info ( "RecursiveStack", "---> End "); processedArray retorno; )else (info ( "RecursiveStack", "profundidade recursiva =" + (processedArray.length + 1)); processedArray.push (arrayToProcess.pop ()); if (arrayToProcess.length> 0) (RecursiveStack arrayToProcess (, processedArray); ) info ( "RecursiveStack", "---> End "); retorno;)) Na implementação vez, a função RecursiveStack implementa uma expectativa. A expectativa é de que, se a função é chamada com um único parâmetro, então é uma chamada a fazer a primeira chamada da recursividade, caso contrário, uma recursão que está acontecendo. A expectativa de saber se uma primeira chamada está acontecendo é determinado pelo código em negrito. Se o segundo parâmetro, processedArray, é indefinido, então a função recursiva inicializa-se e começa a recursividade. Se o segundo parâmetro é definido, então é assumido uma recursão que está acontecendo, ea função irá processar os dados como tal. Antes de continuar, talvez você tenha pego o fato de que RecursiveStack tem dois parâmetros, mas está sendo chamado com um. Anteriormente eu falava sobre as expectativas e que o chamador precisa para passar dois parâmetros. Este exemplo não diz que que o chamador não precisa passar por dois parâmetros, mas sim o exemplo, diz que, se o interlocutor não passe dois parâmetros, a função tem a capacidade para compensar. A mesma função pode ser usada para a inicialização e recursão com base em uma expectativa. Se, entretanto, um chamador define o segundo parâmetro, o que significa que o chamador tem assumido a responsabilidade de implementar a inicialização. Com uma chamada de inicialização definida, RecursiveStack não irá executar uma inicialização e vai saltar diretamente para a funcionalidade de recursão. A vantagem desta solução é que você tem uma função multiuso, sem ter que definir explicitamente uma função de mensagens publicitárias. Você pode estar pensando: "Claro que isso é possível usando uma linguagem como Java ou C # usando funções sobrecarregadas." Sim, é possível usar funções sobrecarregadas, mas, como mencionado anteriormente, uma função sobrecarregada é uma função de mensagens publicitárias que chama a implementação real , ou seja, duas funções precisa ser escrito e mantido. Em JavaScript, tudo pode ser envolvido em uma auto-contido função. Agora que você implementou recursão e sabe a diferença entre uma variável de escopo local e uma variável de escopo global, a pergunta seguinte é: o que acontece se houver duas variáveis com o mesmo nome? Imagine a definição de uma variável em um escopo local que existe em um âmbito global que acontece com o escopo global e localmente declarações de variável? O código a seguir mostra como uma variável é definida a nível mundial em uma função e depois referenciado em outra função. Fonte: / website / ROOT / ajaxrecipes / javascript / variablebehavior.html função GlobalScope () (info ( "GlobalScope (scopedVariable)", typeof (scopedVariable)); scopedVariable = "Globalscope"; info ( "GlobalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable));) function TestScope () (info ( "OtherScope (scopedVariable)", "scopedVariable = "+ scopedVariable + "Type =" ➥ + typeof (scopedVariable));) scopedVariable é definida em GlobalScope e referenciados no TestScope. Como não há var-se declaração de scopedVariable em GlobalScope, scopedVariable é colocado no âmbito global. Running TestScope após GlobalScope resultará em scopedVariable ser definidos globalmente, como mostrado na seguinte saída gerados: Info: GlobalScope (scopedVariable) Info indefinido: GlobalToLocalScope (scopedVariable) scopedVariable = tipo globalscope = Info: string TestScope (scopedVariable) scopedVariable = tipo globalscope = string Na saída gerada, GlobalScope é chamado, e no início da implementação da função, scopedVariable é indefinido. Então scopedVariable é atribuído um buffer, e os resultados gerados scopedVariable indica que não é indefinido e referências de uma seqüência de caracteres. Chamadas TestScope ilustra que scopedVariable é global e é atribuído um buffer. Agora considere o mesmo exemplo, exceto uma variável de escopo global é declarado novamente como um variável local, utilizando a palavra-chave var. Fonte: / website / ROOT / ajaxrecipes / javascript / variablebehavior.html função AlwaysLocalScope () (info ( "GlobalToLocalScope (scopedVariable)", typeof (scopedVariable)); scopedVariable = "AlwaysLocalScope"; info ( "GlobalToLocalScope (scopedVariable)", "scopedVariable = "+ + scopedVariable tipo" ➥ = "+ typeof (scopedVariable)); scopedVariable var;) Na execução da função, scopedVariable primeiro é atribuído um tampão que não use a palavra-chave var. Assim, scopedVariable é declarado no nível de escopo global. Ou pelo menos é isso que você é levado a acreditar. O que acontece é que a variável é declarada no nível local, porque a última instrução da função (em negrito) declara a variável scopedVariable a ser local. Pode parecer estranho que uma variável é declarada a ser local, se em algum lugar da função var palavra-chave é usada. Isso se torna ainda mais estranho, em que, se a palavra-chave var é utilizada em um bloco de decisão que nunca é executado, a variável é ainda declarado local. Para ilustrar, o primeiro a função AlwaysLocal é chamado e, em seguida, TestScope, que gera o seguinte resultado: Info: AlwaysLocalScope (scopedVariable) Info indefinido: AlwaysLocalScope (scopedVariable) scopedVariable = AlwaysLocalScope tipo string = Warn: Erro Geral (scopedVariable não está definido) Quando a função AlwaysLocalScope é chamado, scopedVariable será indefinido, o que significa que não existe em âmbito global, nem local. Então quando a variável é atribuído, a saída gerada terá um valor e tipo. Quando a função TestScope é chamado, é levantada uma exceção porque scopedVariable não está definido. Agora você sabe quando uma variável é declarada em âmbito global e em âmbito local. O último teste é ver o que acontece quando uma variável é declarada tanto em âmbito local e global. O teste envolve chamar as funções na seqüência: GlobalScope, TestScope, AlwaysLocalScope e, em seguida TestScope. Chamar essa seqüência gera o seguinte resultado: Info: GlobalScope (scopedVariable) Info indefinido: GlobalScope (scopedVariable) scopedVariable = tipo globalscope = Info: string TestScope (scopedVariable) scopedVariable = tipo globalscope = Info: string AlwaysLocalScope (scopedVariable) Info indefinido: AlwaysLocalScope (scopedVariable) scopedVariable = tipo AlwaysLocalScope = string Info: TestScope (scopedVariable) scopedVariable = tipo globalscope = string Na saída gerada, scopedVariable é declarada e atribuída em GlobalScope. A função TestScope verifica que scopedVariable existe. Então, quando chamado AlwaysLocalScope, var declara que qualquer referência a scopedVariable dentro da função é uma referência variável local. Assim, se há uma variável definida globalmente com o mesmo nome, não é acessível dentro do escopo da função. Você tem duas maneiras para fazer referência a uma variável global: referenciação através da propriedade janela ou criar uma função que é externo à função de execução (o que significa que não é uma função interna) e atribuindo a variável de escopo global. Quando uma variável não está atribuída, o typeof função retorna indefinido. Depois de atribuir uma variável, typeof retorna outro valor. Se uma variável é definida no contexto de uma função, então cada vez que a função é chamada, a variável antes de ser atribuído será indefinido. A nível global, uma variável pode ser desactivado utilizando o operador de exclusão, da seguinte forma: excluir scopedVariable; Normalmente, o operador delete é usada para redefinir a propriedade de um objeto. Quando eliminar é usado com um identificador, uma referência mundial variável é excluída. Você não pode remover uma referência a uma função usando delete. Vamos testar uma outra variação de alcance utilizando o código dinâmico. Em JavaScript, usando a função eval irá executar um buffer de JavaScript, que testa se uma variável será considerada âmbito global e quando será considerado o âmbito local. A função AlwaysLocalScope, assim, ser modificado. Pela primeira variação, AlwaysLocalScope terá uma alocação dinâmica: AlwaysLocalScope function () (info ( "AlwaysLocalScope (scopedVariable)", typeof (scopedVariable)); eval ( "scopedVariable = 'AlwaysLocalScope'");info ( "AlwaysLocalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable)); scopedVariable var;) O código modificado é mostrado em negrito, ea atribuição de scopedVariable é executado. Usando eval desta maneira não tem efeito, e para a execução dinâmica de código é o mesmo que se o código não tinha sido alterado. A vantagem com eval é que você pode atribuir um pedaço de código para um buffer de texto e executar esse buffer. O âmbito de scopedVariable não foi alterado porque a palavra-chave var ainda existe na declaração da função. A declaração, quando analisado pelo processador JavaScript irá resultar em uma declaração de variável local. Uma forma de mudar o comportamento declaração local é incorporar a declaração de variável em uma instrução eval, como mostra a modificação seguinte código: AlwaysLocalScope function () (info ( "AlwaysLocalScope (scopedVariable)", typeof (scopedVariable)); eval ( "scopedVariable = 'AlwaysLocalScope'");info ( "AlwaysLocalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable)); eval (scopedVariable "var;");) O código modificado em relação ao código AlwaysLocalScope original está em negrito. Desta vez, tanto a atribuição ea declaração de scopedVariable são dinâmicos, o que significa que scopedVariable quando atribuído será tratado como uma variável global. Isso acontece porque quando a primeira instrução eval é executado, não há nenhuma declaração de scopedVariable, eo tempo de execução JavaScript terá loja scopedVariable no espaço global. Para alterar o comportamento e declarar scopedVariable como uma variável local, AlwaysLocalScope precisa ser modificado mais uma vez , como segue: AlwaysLocalScope function () (info ( "AlwaysLocalScope (scopedVariable)", typeof (scopedVariable)); eval (scopedVariable "var;"); eval ( "scopedVariable = 'AlwaysLocalScope'");info ( "AlwaysLocalScope (scopedVariable)", "scopedVariable =" + + scopedVariable ➥ "type =" + typeof (scopedVariable));) Na última modificação, o eval primeiro é a declaração da scopedVariable usando a palavra-chave var. A primeira chamada eval resultados na declaração de scopedVariable como uma variável local. A segunda chamada eval atribui um valor a scopedVariable, que tem como escopo como uma variável local. Quando declarar variáveis no contexto de funções ou no âmbito global, manter os seguintes pontos em mente: • Existem dois escopos para uma variável: local para uma função e global. • Uma variável local é declarado usando a palavra-chave var, com exceção do uso de var em um contexto global. O uso de var não precisa estar no início de uma função. • Uma variável global é declarada quando uma variável é atribuído sem usar a palavra-chave var. • Ela é uma boa prática para declarar variáveis no escopo nível global usando a palavra-chave var. • Local e variáveis globais com o mesmo nome não substituir o outro. Uma variável declarada localmente esconde um mundo variável declarada com o mesmo nome. • Quando uma variável não é declarada, utilizando typeof sobre os resultados variáveis no indefinido. • Você pode unset variáveis globais utilizando o operador delete. • Ao usar funções recursivas, você deve usar as variáveis declaradas localmente. • Recursão normalmente envolve uma inicialização e uma execução. Usando o Javascript, a inicialização ea execução pode ser embrulhado em uma única função. • Embalagem de inicialização e execução em uma única função usa as expectativas, onde a disponibilidade de variáveis é testada para determinar um contexto de chamada. • É possível utilizar o eval para dinamicamente declarar variáveis locais ou globais. Eval • Utilizando faz com que o processador JavaScript para não realizar um olhar em frente na identificação de variáveis locais. Assim, para declarar uma variável local, a palavra-chave var deve ser utilizado antes de atribuir uma variável. • Utilizando a instrução eval, um programa pode determinar dinamicamente ou não uma variável deve ser declarada no âmbito local ou o escopo global. um artigo submetido por Sonja Lande Isenção de responsabilidade:O nosso site não se responsabiliza pelo conteúdo deste artigo. Webarticles é uma fonte de informação livre. Importante: Este artigo "Compreendendo o comportamento das variáveis ao Implementando Recursion" foi traduzida por um software automático. Nós sentimos muito por quaisquer erros de ortografia que pode ter ocorrido. Obrigado pela sua compreensão.
|
|||||
| Online: 259 users browsing the articles directory |
|
|