Os nove erros mais comuns que os desenvolvedores cometem em JavaScript (e como corrigi-los)

Os nove erros mais comuns que os desenvolvedores cometem em JavaScript (e como corrigi-los)

25 de June, 2020 0 By António César de Andrade
Click to rate this post!
[Total: 0 Average: 0]


JavaScript é um linguagem de script usado em páginas da web para adicionar funcionalidade e interatividade. Para um iniciante que vem de uma linguagem de programação diferente, o JavaScript é bastante fácil de entender. Com alguns tutoriais, você deve começar a usá-lo imediatamente.

No entanto, existem alguns erros comuns que muitos programadores iniciantes cometem. Neste artigo, abordaremos nove erros comuns (ou práticas inadequadas) e suas soluções para ajudá-lo a se tornar um desenvolvedor JS melhor.

Confundindo os operadores de atribuição (=) e igualdade (==, ===)

Como o próprio nome indica, o operador de atribuição(=) é usado para atribuir valores a variáveis. Os desenvolvedores costumam confundi-lo com o operador de igualdade.

Aqui está um exemplo:

const name = "javascript";
if ((name = "nodejs")) {
    console.log(name);
}
// output - nodejs

A variável name e a cadeia ‘nodejs’ não são comparadas neste caso. Em vez disso, ‘nodejs’ é designado ao nome e ‘nodejs’ é impresso no console.

Em JavaScript, o sinal de igual duplo (==) e o sinal de igual triplo (===) são chamados operadores de comparação.

Para o código acima, esta é a maneira apropriada de comparar valores:

const name = "javascript";
if (name == "nodejs") {
    console.log(name);
}
// no output
// OR
if (name === "nodejs") {
    console.log(name);
}
// no output

A diferença entre esses operadores de comparação é que o duplo é igual a um solto comparação, enquanto o triplo é igual a rigoroso comparação.

Em uma comparação livre, apenas os valores são comparados. Mas em uma comparação estrita, os valores e o tipo de dados são comparados.

O código a seguir explica melhor:

const number = "1";
console.log(number == 1);
// true
console.log(number === 1);
// false

O número da variável recebeu um valor de sequência igual a 1. Quando comparado com 1 (do tipo de número) usando iguais iguais, ele retorna verdadeiro porque os dois valores são 1.

Porém, quando comparado com o triplo de iguais, ele retorna false porque cada valor tem um tipo de dados diferente.

Esperando que os retornos de chamada sejam síncronos

Os retornos de chamada são uma maneira de o JavaScript manipular operações assíncronas. Promessas e assíncrono / espera, no entanto, são métodos preferíveis para lidar com operações assíncronas, porque vários retornos de chamada levam a inferno de retorno de chamada.

Os retornos de chamada não são síncrono. Eles são usados ​​como uma função a ser chamada após uma operação quando uma execução atrasada é concluída.

Um exemplo é o global setTimeout​ função que recebe uma função de retorno de chamada como seu primeiro argumento e uma duração (em ms) como um segundo argumento da seguinte forma:

function callback() {
​​    console.log("I am the first");
​​}
​​setTimeout(callback, 300);
​​console.log("I am the last");
​​// output
​​// I am the last
​​// I am the first

Após 300 milissegundos, a função de retorno de chamada é chamada. Mas antes que seja concluído, o restante do código é executado. Essa é a razão pela qual o último console.log foi executado primeiro.

Um erro comum que os desenvolvedores cometem é interpretar mal os retornos de chamada como síncronos. Por exemplo, um retorno de chamada que retorna um valor que seria usado para outras operações.

Aqui está esse erro:

function addTwoNumbers() {
​​    let firstNumber = 5;
​​    let secondNumber;
​​    setTimeout(function () {
​​        secondNumber = 10;
​​    }, 200);
​​    console.log(firstNumber + secondNumber);
​​}
​​addTwoNumbers();
​​// NaN

NaNÉ a saída porque secondNumber​ está indefinido. No momento da execução firstNumber + secondNumber, secondNumber ainda está indefinido porque o setTimeout A função executaria o retorno de chamada após 200ms.

A melhor maneira de abordar isso é executar o restante do código na função de retorno de chamada:

function addTwoNumbers() {
​​    let firstNumber = 5;
​​    let secondNumber;
​​    setTimeout(function () {
​​        secondNumber = 10;
​​        console.log(firstNumber + secondNumber);
​​    }, 200);
​​}
​​addTwoNumbers();
​​// 15

Referências erradas a this​

this​ é comum conceito incompreendido em JavaScript. Usar thisEm JavaScript, você realmente precisa entender como funciona, porque funciona de maneira um pouco diferente em comparação com outros idiomas.

Aqui está um exemplo de um erro comum ao usar this​:

const obj = {
​​    name: "JavaScript",
​​    printName: function () {
​​        console.log(this.name);
​​    },
​​    printNameIn2Secs: function () {
​​        setTimeout(function () {
​​            console.log(this.name);
​​        }, 2000);
​​    },
​​};
​​obj.printName();
​​// JavaScript
​​obj.printNameIn2Secs();
​​// undefined

O primeiro resultado é JavaScript Porque this.nameAponta corretamente para a propriedade de nome do objeto. O segundo resultado é undefined Porque this​ perdeu a referência às propriedades do objeto (incluindo o nome).

Isto é porque this​ depende do objeto que chama a função na qual ele vive. Existe um thisVariável em todas as funções, mas o objeto para o qual aponta é determinado pelo objeto que a chama.

o this​ no obj.printName()Aponta diretamente para obj. o thisEm obj.printNameIn2Secs​ aponta diretamente para obj​. Mas o this​ na função de retorno de chamada de setTimeout​ não aponta para nenhum objeto porque nenhum objeto o chamou.

Para um objeto ter chamado setTimeout​, algo como obj.setTimeout...​ seria executado. Como não há objeto chamando essa função, o objeto padrão (que é window) É usado.

O que outras pessoas estão dizendo nameNão existe na janela, resultando em undefined.

As melhores maneiras de manter a referência a thisEm setTimeout é usar bind​, call​, applyOu seta (introduzidas no ES6). Diferentemente das funções normais, as funções de seta não criam suas próprias this.

Portanto, o seguinte manterá sua referência a this​:

​​const obj = {
​​    name: "JavaScript",
​​    printName: function () {
​​        console.log(this.name);
​​    },
​​    printNameIn2Secs: function () {
​​        setTimeout(() => {
​​            console.log(this.name);
​​        }, 2000);
​​    },
​​};
​​obj.printName();
​​// JavaScript
​​obj.printNameIn2Secs();
​​// JavaScript

Desconsiderando a mutabilidade do objeto

Ao contrário dos tipos de dados primitivos, como string, número e assim por diante, nos objetos JavaScript são tipos de dados de referência. Por exemplo, em objetos de valor-chave:

const obj1 = {
​​    name: "JavaScript",
​​};
​​const obj2 = obj1;
​​obj2.name = "programming";
​​console.log(obj1.name);
​​// programming

obj1​ e obj2Possuem a mesma referência ao local na memória em que o objeto está armazenado.

Nas matrizes:

const arr1 = [2, 3, 4];
​​const arr2 = arr1;
​​arr2[0] = "javascript";
​​console.log(arr1);
​​// ['javascript', 3, 4]

Um erro comum que os desenvolvedores cometem é desconsiderar essa natureza do JavaScript e isso resulta em erros inesperados. Por exemplo, se 5 objetos têm a mesma referência ao mesmo objeto, um deles pode interferir nas propriedades em uma base de código em larga escala.

Quando isso acontece, qualquer tentativa de acessar as propriedades originais retornará indefinida ou possivelmente gerará um erro.

A melhor prática para isso é sempre criar novas referências para novos objetos quando você desejar duplicar um objeto. Para fazer isso, o operador restante ( ...​ introduzido no ES6) é uma solução perfeita.

Por exemplo, em objetos de valor-chave:

​​const obj1 = {
​​    name: "JavaScript",
​​};
​​const obj2 = { ...obj1 };
​​console.log(obj2);
​​// {name: 'JavaScript' }
​​obj2.name = "programming";
​​console.log(obj.name);
​​// 'JavaScript'

Nas matrizes:

const arr1 = [2, 3, 4];
​​const arr2 = [...arr1];
​​console.log(arr2);
​​// [2,3,4]
​​arr2[0] = "javascript";
​​console.log(arr1);
​​// [2, 3, 4]

Salvando matrizes e objetos no armazenamento do navegador

Às vezes, ao trabalhar com JavaScript, os desenvolvedores podem querer tirar proveito do localStorage para salvar valores. Mas um erro comum é tentar salvar matrizes e objetos como está no localStorage. localStorage aceita apenas strings.

Na tentativa de salvar objetos, o JavaScript converte o objeto em uma sequência. O resultado é [Object Object] para objetos e uma sequência separada por vírgula para elementos da matriz.

Por exemplo:

​​const obj = { name: "JavaScript" };
​​window.localStorage.setItem("test-object", obj);
​​console.log(window.localStorage.getItem("test-object"));
​​// [Object Object]
​​const arr = ["JavaScript", "programming", 45];
​​window.localStorage.setItem("test-array", arr);
​​console.log(window.localStorage.getItem("test-array"));
​​// JavaScript, programming, 45

Quando objetos são salvos assim, torna-se difícil acessá-los. Para o exemplo de objeto, acessando o objeto como .name​ resultaria em um erro. Isto é porque [Object Object] é uma string agora, sem um ​name propriedade.

Uma maneira melhor de salvar objetos e matrizes no armazenamento local é usando JSON.stringify​(para converter objetos em cadeias) e JSON.parse​ (para converter seqüências de caracteres em objetos). Dessa forma, acessar os objetos fica fácil.

A versão correta do código acima seria:

​​const obj = { name: "JavaScript" };
​​window.localStorage.setItem("test-object", JSON.stringify(obj));
​​const objInStorage = window.localStorage.getItem("test-object");
​​console.log(JSON.parse(objInStorage));
​​// {name: 'JavaScript'}
​​const arr = ["JavaScript", "programming", 45];
​​window.localStorage.setItem("test-array", JSON.stringify(arr));
​​const arrInStorage = window.localStorage.getItem("test-array");
​​console.log(JSON.parse(arrInStorage));
​​// JavaScript, programming, 45

Não está usando valores padrão

Configuração valores padrão em variáveis ​​dinâmicas é uma prática muito boa para evitar erros inesperados. Aqui está um exemplo de um erro comum:

function addTwoNumbers(a, b) {
​​    console.log(a + b);
​​}
​​addTwoNumbers();
​​// NaN

O resultado é NaN​ Porque aÉ undefinedE bÉ undefined​. Usando valores padrão, erros como esse podem ser evitados. Por exemplo:

function addTwoNumbers(a, b) {
​​    if (!a) a = 0;
​​    if (!b) b = 0;
​​    console.log(a + b);
​​}
​​addTwoNumbers();
​​// 0

Como alternativa, o recurso de valor padrão introduzido no ES6 pode ser usado da seguinte maneira:

​​function addTwoNumbers(a = 0, b = 0) {
​​    console.log(a + b);
​​}
​​addTwoNumbers();
​​// 0

Este exemplo, embora mínimo, enfatiza a importância dos valores padrão. Além disso, os desenvolvedores podem fornecer erros ou mensagens de aviso quando os valores esperados não são fornecidos.

Nomeação incorreta de variáveis

Sim, os desenvolvedores ainda cometem esse erro. Nomear é difícil, mas os desenvolvedores realmente não têm escolha. Comentários são boas práticas de programação, assim como nomear variáveis.

Por exemplo:

function total(discount, p) {
​​    return p * discount
​​}

A variável discountEstá bem, mas e quanto a pOu total​? Total de quê? Uma prática melhor para o acima seria:

function totalPrice(discount, price) {
​​    return discount * price
​​}

A nomeação correta de variáveis ​​é importante porque um desenvolvedor pode nunca ser o único desenvolvedor em uma base de código em um momento específico ou no futuro.

A nomeação de variáveis ​​corretamente permitirá que os colaboradores entendam facilmente como um projeto funciona.

Check-up para valores booleanos

const isRaining = false
​​if(isRaining) {
​​    console.log('It is raining')
​​} else {
​​    console.log('It is not raining')
​​}
​​// It is not raining

É prática comum verificar valores booleanos como visto no código acima. Enquanto isso estiver correto, ocorrerão erros ao testar alguns valores.

Em JavaScript, uma comparação livre de 0E falseRetorna true e 1E true​ retorna true. Isso significa que se isRainingEra 1, isRainingSeria true.

Este também é um erro geralmente cometido em objetos. Por exemplo:

const obj = {
​​    name: 'JavaScript',
​​    number: 0
​​}
​​if(obj.number) {
​​    console.log('number property exists')
​​} else {
​​    console.log('number property does not exist')
​​}
​​// number property does not exist

Apesar de numberPropriedade existe, obj.numberRetorna 0, que é um falsy valor, portanto, o else​ bloco é executado.

Portanto, a menos que você tenha certeza do intervalo de valores que seria usado, valores e propriedades booleanos nos objetos devem ser testados da seguinte maneira:

if(a === false)...
if(object.hasOwnProperty(property))...

Adição e concatenação confusas

O sinal de mais (+) possui duas funções no JavaScript: adição e concatenação. A adição é para números e a concatenação é para seqüências de caracteres. Alguns desenvolvedores costumam usar mal esse operador.

Por exemplo:

const num1 = 30;
​​const num2 = "20";
​​const num3 = 30;
​​const word1 = "Java"
​​const word2 = "Script"
​​console.log(num1 + num2);
​​// 3020
​​console.log(num1 + num3);
​​// 60
​​console.log(word1 + word2);
​​// JavaScript
​​

Ao adicionar strings e números, o JavaScript converte os números em strings e concatena todos os valores. Para adição de números, é executada uma operação matemática.

Conclusão

É claro que existem mais erros (alguns triviais, outros graves) do que os listados acima. Portanto, mantenha-se atualizado com os desenvolvimentos no idioma.

Estudar e evitar esses erros o ajudará a criar aplicativos e ferramentas da Web melhores e mais confiáveis.



Fonte