O design da linguagem Javascript não é suficientemente rigoroso e erros podem ocorrer em muitos lugares se você não tomar cuidado.
Por exemplo, considere a seguinte situação.
Agora, precisamos determinar se existe um objeto global myObj. Se não existir, declare-o. O algoritmo descrito em linguagem natural é o seguinte:
Copie o código do código da seguinte forma:
if (meuObj não existe){
declare meuObj;
}
Você pode pensar que escrever esse código é fácil. Mas, na verdade, as questões gramaticais envolvidas são muito mais complexas do que imaginamos. Juriy Zaytsev apontou que existem mais de 50 maneiras de determinar se um objeto Javascript existe. Somente se você tiver muita clareza sobre os detalhes de implementação da linguagem Javascript você poderá perceber a diferença entre eles.
A primeira maneira de escrever
Intuitivamente, você pode pensar que poderia escrever:
Copie o código do código da seguinte forma:
if (!meuObj) {
meuObj = { };
}
Porém, ao executar este código, o navegador lançará diretamente um erro ReferenceError, fazendo com que a operação seja interrompida. O que está errado?
A propósito, quando a instrução if determina se myObj está vazio, a variável ainda não existe, então um erro é relatado. Altere-o para o seguinte e ele será executado corretamente.
Copie o código do código da seguinte forma:
if (!meuObj) {
var meuObj = { };
}
Por que não há erro após adicionar um var? Será que neste caso, quando a instrução if faz um julgamento, myObj já existe?
Para responder a esta pergunta, você deve saber como funciona o interpretador Javascript. A linguagem Javascript é "analisar primeiro, executar depois". A declaração da variável já foi concluída durante a análise, portanto o código acima é na verdade equivalente a:
Copie o código do código da seguinte forma:
var meuObj;
if (!meuObj) {
var meuObj = { };
}
Portanto, quando a instrução if faz um julgamento, myObj já existe, portanto nenhum erro é relatado. Este é o efeito de "elevação" do comando var. O interpretador Javascript apenas "promove" variáveis definidas pelo comando var e não funciona em variáveis que são atribuídas diretamente sem usar o comando var. É por isso que um erro será relatado se var não for adicionado.
A segunda maneira de escrever
Além do comando var, há outra reescrita que também pode obter os resultados corretos:
Copie o código do código da seguinte forma:
if (!window.myObj) {
meuObj = { };
}
Window é o objeto de nível superior do JavaScript e todas as variáveis globais são suas propriedades. Portanto, determinar se myobj está vazio é equivalente a determinar se o objeto window possui o atributo myobj, de modo que erros ReferenceError que ocorrem porque myObj não está definido possam ser evitados. Porém, a partir da padronização do código, o melhor é adicionar var na segunda linha:
Copie o código do código da seguinte forma:
if (!window.myObj) {
var meuObj = { };
}
Ou escrito assim:
if (!window.myObj) {
janela.meuObj = { };
}
A terceira maneira de escrever
A desvantagem do método de escrita acima é que em alguns ambientes em execução (como V8, Rhino), a janela pode não ser um objeto de nível superior. Então, considere reescrevê-lo como:
Copie o código do código da seguinte forma:
if (!this.meuObj) {
este.meuObj = { };
}
No nível das variáveis globais, a palavra-chave this sempre aponta para a variável de nível superior, portanto pode ser independente de diferentes ambientes em execução.
A quarta maneira de escrever
No entanto, a forma de escrever acima é menos legível e o ponteiro é variável e sujeito a erros, então reescrevemos ainda mais:
Copie o código do código da seguinte forma:
var global = isto;
if (!global.myObj) {
global.meuObj = { };
}
É muito mais claro usar a variável personalizada global para representar o objeto de nível superior.
A quinta maneira de escrever
Você também pode usar o operador typeof para determinar se myObj está definido.
Copie o código do código da seguinte forma:
if (typeof meuObj == "indefinido") {
var meuObj = { };
}
Este é atualmente o método mais utilizado para determinar se um objeto JavaScript existe.
A sexta maneira de escrever
Como o valor de myObj é diretamente igual a indefinido quando é definido, mas não atribuído, o método de escrita acima pode ser simplificado:
Copie o código do código da seguinte forma:
if (meuObj == indefinido) {
var meuObj = { };
}
Há duas coisas a serem observadas aqui. Primeiro, a palavra-chave var na segunda linha não pode estar faltando, caso contrário, ocorrerá um ReferenceError. Em segundo lugar, indefinido não pode ser adicionado com aspas simples ou duplas, porque o tipo de dados indefinido é comparado aqui, não "indefinido "Esta string.
A sétima maneira de escrever
O método de escrita acima ainda é válido no caso de "comparação exata" (===):
Copie o código do código da seguinte forma:
if (meuObj === indefinido) {
var meuObj = { };
}
A oitava maneira de escrever
De acordo com o design da linguagem JavaScript, indefinido == nulo, portanto, comparar se myObj é igual a nulo também pode obter o resultado correto:
Copie o código do código da seguinte forma:
if (meuObj == nulo) {
var meuObj = { };
}
No entanto, embora os resultados correntes estejam corretos, do ponto de vista semântico, este método de julgamento está errado e deve ser evitado. Porque nulo se refere a um objeto vazio ao qual foi atribuído um valor nulo, ou seja, esse objeto na verdade tem um valor, enquanto indefinido se refere a um objeto que não existe ou não tem valor atribuído. Portanto, apenas o "operador de comparação" (==) pode ser usado aqui. Se o "operador de comparação exato" (===) for usado aqui, ocorrerá um erro.
A nona maneira de escrever
Você também pode usar o operador in para determinar se myObj é um atributo do objeto de nível superior:
Copie o código do código da seguinte forma:
if (!('meuObj' na janela)) {
janela.meuObj = { };
}
A décima maneira de escrever
Finalmente, use o método hasOwnProperty para determinar se myObj é uma propriedade do objeto de nível superior:
Copie o código do código da seguinte forma:
if (!this.hasOwnProperty('meuObj')) {
este.meuObj = { };
}
Resumir
1. Se você apenas determinar se o objeto existe, é recomendável usar o quinto método de escrita.
2. Se além de saber se o objeto existe, você também precisa determinar se o objeto possui valor nulo, é recomendável usar a primeira forma de escrita.
3. A menos que haja circunstâncias especiais, todas as variáveis devem ser declaradas usando o comando var.
4. Para ser multiplataforma, é recomendável evitar o uso de janelas para representar objetos de nível superior.
5. Na linguagem Javascript, nulo e indefinido são facilmente confundidos. Nos casos em que ambos possam estar envolvidos, recomenda-se utilizar o operador de “comparação exata” (===).