Como desmarcar uma variável JavaScript?
Eu tenho uma variável global em JavaScript (na verdade uma windowpropriedade, mas acho que não importa) que já foi preenchida por um script anterior, mas não quero outro script que seja executado mais tarde para ver seu valor ou até mesmo definiram.
Eu coloquei some_var = undefinede funciona com a finalidade de testar, typeof some_var == "undefined"mas realmente não acho que seja o caminho certo a fazer.
O deleteoperador remove uma propriedade de um objeto. Não pode remover uma variável. Portanto, a resposta para a pergunta depende de como a variável ou propriedade global é definida.
(1) Se for criado com var, não poderá ser excluído.
(2) Se for criado sem var, poderá ser excluído.
1. Usando var
Nesse caso, a referência g_aé criada no que a especificação ECMAScript chama de " VariableEnvironment " anexada ao escopo atual - este pode ser o contexto de execução de uma função no caso de usar vardentro de uma função (embora possa ser um pouco mais complicado quando você considera let) ou no caso de código "global", o VariableEnvironment é anexado ao objeto global (geralmente window).
Referências no VariableEnvironment normalmente não são deletable - o processo detalhado no ECMAScript 10,5 explica isso em detalhes, mas basta dizer que a menos que o código é executado em um evalcontexto (que a maioria dos consoles de desenvolvimento baseados em navegador usar), então as variáveis declaradas com varnão pode ser excluído.
2. Sem usar var
Ao tentar atribuir um valor a um nome sem usar a varpalavra - chave, o Javascript tenta localizar a referência nomeada no que a especificação ECMAScript chama de " LexicalEnvironment " e a principal diferença é que LexicalEvironment está aninhado - ou seja, um LexicalEnvironment tem um pai ( o que a especificação ECMAScript chama de "referência do ambiente externo") e quando o Javscript falha ao localizar a referência em um LexicalEenvironment , ele procura no LexicalEnvironment pai (conforme detalhado em 10.3.1 e 10.2.2.1 ). O LexicalEnvironment de nível superior é o " ambiente global", e que está vinculado ao objeto global, em que suas referências são as propriedades do objeto global. Portanto, se você tentar acessar um nome que não foi declarado usando uma varpalavra - chave no escopo atual ou em qualquer escopo externo, o Javascript eventualmente buscará uma propriedade do windowobjeto para servir como essa referência.Como aprendemos antes, as propriedades dos objetos podem ser excluídas.
É importante lembrar que as vardeclarações são "içadas" - isto é, sempre são consideradas como ocorridas no início do escopo em que estão - embora não seja a inicialização de valor que pode ser feita em uma varinstrução - que é deixada onde está. . Portanto, no código a seguir, aé uma referência do VariableEnvironment e não a windowpropriedade e seu valor estará 10no final do código:
A discussão acima é quando o "modo estrito" não está ativado. As regras de pesquisa são um pouco diferentes ao usar o "modo estrito" e as referências lexicais que teriam resolvido as propriedades da janela sem o "modo estrito" gerarão erros "variáveis ​​não declaradas" em "modo estrito". Eu realmente não entendi onde isso é especificado, mas é como os navegadores se comportam.
O que você disse é um equívoco comum, mas na verdade está incorreto - no Javascript não há "variáveis ​​globais". Variáveis ​​definidas sem um escopo explícito (como usar varfora de uma função) são propriedades do "objeto global", que é o que ocorre nos navegadores da web window. Então - var a = 1; delete window.a; console.log(a);excluirá a variável com êxito e fará com que a última linha emita um erro de referência.
@Guss, seu código var a = 1; delete window.a; console.log(a);exibe 1. #
Estou usando o Google Chrome v36. Eu testei em outros navegadores. Parece que não é consistente entre navegadores. O Chrome e o Opera exibiram 1, enquanto o Firefox, Safari e IE 11 no meu computador apresentaram um erro.
Ok, meu erro. Veja ecma-international.org/ecma-262/5.1/#sec-10.5 (sub-pontos 2 e 8.c.ii): Ao executar meu teste no console do desenvolvedor, geralmente é considerado "contexto de avaliação" (embora talvez não no Chrome), então isso gera um erro. O mesmo código no contexto global de um documento real será exibido 1corretamente em todos os navegadores. Executando em documentos reais, seus exemplos de código estão corretos. Selecionei sua resposta como correta, mas agradeceria se você pudesse editá-la para incluir explicações window.a = 1; delete window.a;e possivelmente o mecanismo. Eu também posso fazer isso se você não se importar.
@KlaiderKlai yes. As variáveis ​​com escopo da função são criadas e destruídas sempre que a função é executada. Provavelmente o fechamento é uma exceção.
A resposta da @ scunlife funcionará, mas tecnicamente deve ser
delete é suposto não funcionar quando o destino não é uma propriedade de objeto. por exemplo,
Mas como as variáveis ​​globais são na verdade membros do objeto window, ele funciona.
Quando cadeias de protótipos estão envolvidas, o uso de delete fica mais complexo, pois remove apenas a propriedade do objeto de destino, e não o protótipo. por exemplo,
EDIT: Minha resposta é um pouco imprecisa (consulte "Conceitos errados " no final). O link explica todos os detalhes sangrentos, mas o resumo é que pode haver grandes diferenças entre os navegadores e dependendo do objeto do qual você está excluindo. delete object.somePropgeralmente deve ser seguro enquanto object !== window. Eu ainda não o usaria para excluir variáveis ​​declaradas com, varembora você possa, nas circunstâncias certas.
obrigado @jedierikb pelo link para esse artigo interessante. mais especificamente a esta parte < perfectionkills.com/understanding-delete/#misconceptions > daquele artigo em que o autor afirma que a declaração de noah "excluir é suposto ser um não-op" é bastante imprecisa, juntamente com uma excelente exlpanação, por que é imprecisa . (Não atire o mensageiro!)
Em relação à última sentença da resposta revisada, a única circunstância na qual você pode excluir variáveis ​​declaradas com varé quando a variável foi declarada com eval.
— Stephen Booher
Nesse caso , a instrução delete não parece fazer nada. O que está acontecendo aqui?
@ AndersonGreen - variáveis ​​globais decalcadas são criadas com o sinalizador DontDelete para que não sejam deletáveis. Esse código se comporta exatamente como o esperado.
Se você estiver declarando implicitamente a variável sem var, a maneira correta seria usar delete foo.
No entanto, após a exclusão, se você tentar usá-lo em uma operação como a adição a ReferenceError, será lançada porque você não pode adicionar uma string a um identificador não declarado e indefinido. Exemplo:
Em algumas situações, pode ser mais seguro atribuí-lo a falso, nulo ou indefinido, para que seja declarado e não gerará esse tipo de erro.
Note que no ECMAScript null, false, undefined, 0, NaN, ou ''que todos avaliar a false. Apenas certifique-se de não usar o !==operador; em vez disso, !=ao digitar booleanos e não desejar a verificação de identidade (o nullfaria == falseefalse == undefined ).
Observe também que deletenão "exclui" referências, mas apenas propriedades diretamente no objeto, por exemplo:
Se você declarou uma variável com, varnão pode excluí-la:
No Rhino:
Também não é possível excluir algumas propriedades predefinidas, como Math.PI:
Existem algumas exceções estranhas a deletequalquer idioma, se você se importa o suficiente, você deve ler:
Obrigado pela resposta completa com todos os detalhes. Marquei isso para isso, mas aceitei a resposta de Noah porque acredito que, para uma simples pergunta, a brevidade é mais importante do que a conclusão. Mais uma vez - obrigado pelo excelente trabalho que você fez nesta resposta.
Isso não funciona se o escopo deste código for uma função. Veja a resposta de @ noah para a solução correta.
— Roatin Marth 20/10/2009
Obrigado pela resposta, mas aceitei a resposta de Noé porque explica melhor as armadilhas do delete.
não se preocupe ... Eu dei uma resposta simples "rápido e sujo" - @noah adicionou todos os detalhes para os "outros" casos, assim ele também merece crédito. ;-)
— scunliffe 22/10/09
Isso não está correto. deletesó funciona para uma propriedade. Definindo nulla variável ainda existe.
Esta resposta é boa o suficiente para o caso mais provável em que você verifica com "if (some_var) {..}" #
TLDR: simples definido variáveis (sem var, let, const) poderia ser suprimida com delete. Se você usar var, let, const- não podiam ser apagados nem com deletenem com Reflect.deleteProperty.
FF Nightly 53.0a1 mostra o mesmo comportamento.
— Serj.by
Sua resposta está tecnicamente correta, então você entendeu, mas tudo o que você escreveu é coberto pela resposta selecionada com muito mais detalhes e referências às especificações do ECMAScript - no futuro, seria útil revisar a resposta existente antes de postar.
Acordado. Mas mencionou apenas um varcaso. Quanto a mim foi interessante para testar e participação lete constcasos bem. No entanto, obrigado pela observação. Tentará ser mais específico da próxima vez.
O ECMAScript 2015 oferece a API Reflect. É possível excluir a propriedade do objeto com Reflect.deleteProperty () :
Para excluir a propriedade do windowobjeto global :
Em alguns casos, as propriedades não podem ser excluídas (quando a propriedade não é configurável) e, em seguida, essa função retorna false(assim como o operador delete ). Em outros casos, retornos true:
Há uma diferença entre deletePropertyfunção e deleteoperador quando executada no modo estrito:
— madox2
Variáveis, em contraste com propriedades simples, têm o atributo [[Configurable]] , significando impossibilidade de remover uma variável através do operador delete . No entanto, há um contexto de execução no qual esta regra não afeta. É o contexto eval : o atributo [[Configurable]] não está definido para variáveis.
O operador de exclusão remove uma propriedade de um objeto.
De acordo com a pergunta, você precisa de um dos seguintes
Além do que todos haviam escrito, observe também que delete retorna booleano. Pode dizer se a exclusão foi bem-sucedida ou não.
Testando no Chrome, tudo exceto letfoi delicioso. quando deleteretornado true, na verdade os removeu:
Nem sempre é correto. Especialmente no Chrome. O Firefox retorna tudo corretamente. Não testou em nenhum outro navegador. Quanto aos letvars e constvars, ele retorna true, o que deve significar que a variável foi excluída, mas não é. Você pode verificá-lo no Chrome e no FF. O FF parece retornar valores corretos, enquanto o Chrome não está. Portanto, não tenha certeza de que você realmente pode confiar nisso. Vamos ver:let letVar = "1"; undefined delete letVar; true letVar "1" typeof letVar; "string" const constVar="1"; undefined delete constVar; true constVar; "1" typeof constVar; "string"
Como jedierikb mencionado abaixo, há um artigo perfeito de kangax perfectionkills.com/understanding-delete que descreve principalmente por que e como o deleteoperador trabalha. Mas não está descrevendo por que literalmente opõe a situação às funções. Que pena. No entanto, em relação às variáveis, as coisas começam a parecer muito mais claras.
Você não pode excluir uma variável se a declarar (com var x;) no momento do primeiro uso. No entanto, se sua variável x apareceu pela primeira vez no script sem uma declaração, você pode usar o operador delete (delete x;) e sua variável será excluída, muito semelhante a excluir um elemento de uma matriz ou excluir uma propriedade de um objeto .
— Satyapriya Mishra
Estou um pouco confuso. Se tudo o que você deseja é que um valor de variável não passe para outro script, não há necessidade de excluir a variável do escopo. Simplesmente anule a variável e verifique explicitamente se é ou não nula. Por que enfrentar o problema de excluir a variável do escopo? Que finalidade esse servidor que anula não pode?
— designdrumm
O requisito é que o script de pedido, que não está sob meu controle, não veja a variável existir - especificamente para o caso do OP, o script de destino tem um comportamento para o nullvalor que eu não quero acionar.
Nenhum "back-end" foi abusado durante a produção desta pergunta. Estes são apenas alguns scripts em um site onde eu não tenho controle de nada, exceto esse script.
Os dois scripts estão no mesmo documento ou em documentos separados que um chama o outro para carregar? Você mencionou o script do pedido e o script de destino. Se for uma questão de uma variável ser transmitida para outro script por meio de uma variável get / post, eu a excluiria no back-end antes de qualquer javascript colocar as mãos nela. Um exemplo disso no php seria algo como. <?php if(isset($_POST['somevariable']) unset($_POST['somevariable']); if(isset($_GET['somevariable']) unset($_GET['somevariable']); ?>
— Designdrumm 15/04/19
Eu vejo. Bem, se houver verificações e balanços para null, defini-lo como um valor com o qual o script de destino não fará nada parece mais lógico do que excluir uma variável do escopo, mas você deve ter sua resposta, então deixarei o cavalo descansar. Obrigado por suas respostas.
Uma pergunta rápida. Alguma vez haverá um script chamado após o seu que não estará sob seu controle, mas ainda precisará dessa variável? Nesse caso, excluir a variável do escopo é uma má ideia.