Erros de JavaScript


Índice

    Mostrar índice


Este capítulo aponta alguns erros comuns de JavaScript.


Usando acidentalmente o operador de atribuição

Programas JavaScript podem gerar resultados inesperados se um programador acidentalmente usa um operador de atribuição (=), em vez de um operador de comparação (==) em uma instrução if.

Esta instrução if retorna false (como esperado) porque x é diferente de 10:

let x = 0;
if (x == 10) 

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Comparisons</h2>

<p>This returns false (as expected) because x is not equal to 10:</p>

<p id="demo"></p>

<script>
let x = 0;
document.getElementById("demo").innerHTML = Boolean(x == 10);
</script>

</body>
</html>

Esta instrução if retorna true (talvez não como esperado), porque 10 é verdadeiro:

let x = 0;
if (x = 10)

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>This returns true (maybe not as expected), because 10 is true:</p>

<p id="demo"></p>

<script>
let x = 0;
document.getElementById("demo").innerHTML = Boolean(x = 10);
</script>

</body>
</html>

Esta instrução if retorna false (talvez não como esperado), porque 0 é falso:

let x = 0;
if (x = 0)

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>This if statement returns false (maybe not as expected), because 0 is false:</p>

<p id="demo"></p>

<script>
let x = 0;
document.getElementById("demo").innerHTML = Boolean(x = 0);
</script>

</body>
</html>

Uma atribuição sempre retorna o valor da atribuição.


Esperando uma comparação frouxa

Na comparação regular, o tipo de dados não importa. Esta instrução if retorna verdadeiro:

let x = 10;
let y = "10";
if (x == y) 

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>In regular comparison, data type does not matter. This if statement returns true:</p>

<p id="demo"></p>

<script>
let x = 10;
let y = "10";
document.getElementById("demo").innerHTML = Boolean(x == y);
</script>

</body>
</html>

Em comparação estrita, o tipo de dados é importante. Esta instrução if retorna falso:

let x = 10;
let y = "10";
if (x === y) 

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>In strict comparison, data type does matter. This if statement returns false:</p>

<p id="demo"></p>

<script>
let x = 10;
let y = "10";
document.getElementById("demo").innerHTML = Boolean(x === y);
</script>

</body>
</html>

É um erro comum esquecer que as instruções switch usam instruções estritas comparação:

Esta opção de caso exibirá um alerta:

let x = 10;
switch(x) {
  case 10: alert("Hello");
    } 

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>It is a common mistake to forget that switch statements use strict comparison.</p>
<p>This will work:</p>

<p id="demo"></p>

<script>
let x = 10;
switch(x) {
  case 10: document.getElementById("demo").innerHTML = "Hello";
}
</script>

</body>
</html>

Esta opção de caso não exibirá um alerta:

let x = 10;
switch(x) {
  case "10": alert("Hello");
    } 

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>It is a common mistake to forget that switch statements use strict comparison.</p>
<p>This will not work:</p>

<p id="demo"></p>

<script>
let x = 10;
switch(x) {
  case "10": document.getElementById("demo").innerHTML = "Hello";
}
</script>

</body>
</html>


Adição e concatenação confusas

Adição significa somar números.

Concatenação consiste em adicionar strings.

Em JavaScript ambas as operações usam o mesmo operador +.

Por causa disso, adicionar um número como um número produzirá um resultado diferente resultado da adição de um número como uma string:

let x = 10;
x = 10 + 5;       // 
    Now x is 15

let y = 10;
y += "5";        
    // Now y is "105"

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>Adding a number as a number produces a different result from adding a number as a string:</p>

<p id="demo"></p>

<script>
let y = 10
y += "5";
document.getElementById("demo").innerHTML = y;
</script>

</body>
</html>

Ao adicionar duas variáveis, pode ser difícil antecipar o resultado:

let x = 10;
let y = 5;
let z = x + y;     // Now z is 15

let x = 10;
let y = "5";
let z = x + y;     // Now z is "105"

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>Adding a number as a number produces a different result from adding a number as a string:</p>

<p id="demo"></p>

<script>
let x = 10;
let y = "5";
let z = x + y;
document.getElementById("demo").innerHTML = z;
</script>

</body>
</html>

Incompreensão dos carros alegóricos

Todos os números em JavaScript são armazenados como números de ponto flutuante de 64 bits (flutua).

Todas as linguagens de programação, incluindo JavaScript, têm dificuldades com valores precisos de ponto flutuante:

let x = 0.1;
let y = 0.2;
let z = x + y            
    // the result in z will not be 0.3

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>All programming languages, including JavaScript, have difficulties with precise floating point values:</p>

<p id="demo"></p>

<script>
let x = 0.1;
let y = 0.2;
let z = x + y;
document.getElementById("demo").innerHTML = z;
</script>

</body>
</html>

Para resolver o problema acima, ajuda multiplicar e dividir:

Exemplo

let z = (x * 10 + y * 10) / 10;       // z will be 0.3

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>All programming languages, including JavaScript, have difficulties with precise floating point values.</p>
<p>To solve the problem, it helps to multiply and divide:</p>

<p id="demo"></p>

<script>
let x = 0.1;
let y = 0.2;
let z = (x * 10 + y *10) / 10;
document.getElementById("demo").innerHTML = z;
</script>

</body>
</html>


Quebrando uma string JavaScript

JavaScript permitirá que você divida uma instrução em duas linhas:

Exemplo 1

let x =
"Hello World!";

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Breaking a JavaScript Statement</h2>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML =
"Hello World!";
</script>

</body>
</html>

Mas quebrar uma instrução no meio de uma string não funcionará:

Exemplo 2

let x = "Hello
World!";

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>
<p>Breaking a statement in the middle of a string will not work:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = "Hello 
World!";
</script>

</body>
</html>

Você deve usar uma "barra invertida" se precisar quebrar uma instrução em uma string:

Exemplo 3

let x = "Hello \
World!";

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>You must use a "backslash" if you must break a statement in a string:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = "Hello \
World!";
</script>

</body>
</html>

Colocação errada de ponto e vírgula

Devido a um ponto e vírgula mal colocado, este bloco de código será executado independentemente de o valor de x:

if (x == 19);
{
    // code block  
}

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p id="demo"></p>

<script>
let x = 5;
if (x == 19);
{
document.getElementById("demo").innerHTML = "Hello";
}
</script>

</body>
</html>

Quebrando uma declaração de retorno

É um comportamento padrão do JavaScript fechar uma instrução automaticamente no fim de uma linha.

Por causa disso, esses dois exemplos retornarão o mesmo resultado:

Exemplo 1

function myFunction(a) {
    let power = 10  
  return a * power
}

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>This example will return a correct result:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = myFunction(55);
function myFunction(a) {
  let power = 10
  return a * power
}
</script>

</body>
</html>

Exemplo 2

function myFunction(a) {
    let power = 10;
  return a * power;
}

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>This example will return a correct result:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = myFunction(55);
function myFunction(a) {
  let power = 10;
  return a * power;
}
</script>

</body>
</html>

JavaScript também permitirá que você divida uma instrução em duas linhas.

Por causa disso, o exemplo 3 também retornará o mesmo resultado:

Exemplo 3

function myFunction(a) {
    let
  power = 10;  
  return a * power;
}

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>This example will return a correct result:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = myFunction(55);
function myFunction(a) {
  let
  power = 10;
  return a * power;
}
</script>

</body>
</html>

Mas, o que acontecerá se você quebrar a instrução return em duas linhas como esse:

Exemplo 4

function myFunction(a) {
    let
  power = 10;  
  return
  a * power;
}

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>This example will return undefined:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = myFunction(55);
function myFunction(a) {
  let
  power = 10;
  return
  a * power;
}
</script>

</body>
</html>

A função retornará indefinido!

Por que? Porque JavaScript pensou que você quis dizer:

Exemplo 5

function myFunction(a) {
    let
  power = 10;  
  return;
  a * power;
}

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>Common JavaScript Mistakes</h2>

<p>This example will return undefined:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = myFunction(55);
function myFunction(a) {
  let
  power = 10;
  return;
  a * power;
}
</script>

</body>
</html>

Explicação

Se uma declaração estiver incompleta como:

let

JavaScript tentará completar a instrução lendo a próxima linha:

 power = 10;

Mas como esta declaração está completa:

 return

JavaScript irá fechá-lo automaticamente assim:

 return;

Isso acontece porque as instruções de fechamento (finalização) com ponto e vírgula são opcionais em JavaScript.

JavaScript fechará a instrução return no final da linha, porque é uma declaração completa.

Nunca quebre uma declaração de retorno.


Acessando matrizes com índices nomeados

Muitas linguagens de programação oferecem suporte a arrays com índices nomeados.

Matrizes com índices nomeados são chamadas associativas matrizes (ou hashes).

JavaScript não suporta arrays com índices nomeados.

Em JavaScript, arrays usam índices numerados:

Exemplo

const person = [];
person[0] = "John";
person[1] = "Doe";
person[2] = 46;
person.length;       
 // person.length will return 3
person[0];           
 // person[0] will return "John"

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Arrays</h1>

<p id="demo"></p>

<script>
const person = [];
person[0] = "John";
person[1] = "Doe";
person[2] = 46; 
document.getElementById("demo").innerHTML =
person[0] + " " + person.length;
</script>

</body>
</html>

Em JavaScript, objetos usam índices nomeados.

Se você usar um índice nomeado, ao acessar um array, o JavaScript irá redefinir a matriz para um objeto padrão.

Após a redefinição automática, os métodos e propriedades do array produzirão valores indefinidos ou resultados incorretos:

Exemplo :

const person = [];
person["firstName"] = "John";
person["lastName"] = "Doe";
person["age"] = 46;
person.length;      // person.length will 
 return 0
person[0];          
 // person[0] will return undefined

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Arrays</h1>

<p>If you use a named index when accessing an array, JavaScript will redefine the array to a standard object, and some array methods and properties will produce undefined or incorrect results.</p>

<p id="demo"></p>

<script>
const person = [];
person["firstName"] = "John";
person["lastName"] = "Doe";
person["age"] = 46; 
document.getElementById("demo").innerHTML =
person[0] + " " + person.length;
</script>

</body>
</html>


Terminando as definições com uma vírgula

Vírgulas finais na definição de objeto e array são legais no ECMAScript 5.

Exemplo de objeto:

person = {firstName:"John", lastName:"Doe", age:46,}

Exemplo de matriz:

points = [40, 100, 1, 5, 25, 10,];

AVISO !!

O Internet Explorer 8 irá travar.

JSON não permite vírgulas finais.

JSON:

person = {"firstName":"John", "lastName":"Doe", "age":46}

JSON:

points = [40, 100, 1, 5, 25, 10];

Indefinido não é nulo

Objetos, variáveis, propriedades e métodos JavaScript podem ser indefinidos.

Além disso, objetos JavaScript vazios podem ter o valor null.

Isso pode dificultar um pouco testar se um objeto está vazio.

Você pode testar se um objeto existe testando se o tipo é indefinido:

Exemplo :

if (typeof myObj === "undefined") 

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Objects</h2>

<p>To test if an object does not exist, test if the type is undefined:</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = typeof myObj === "undefined";
</script>

</body>
</html>

Mas você não pode testar se um objeto é null, porque isso gerará um erro se o objeto é indefinido:

Incorreta:

if (myObj === null)  

Para resolver este problema, você deve testar se um objeto não é nulo, e não indefinido.

Mas isso ainda pode gerar um erro:

Incorreta:

if (myObj !== null && typeof myObj 
  !== "undefined")  

Por causa disso, você deve testar not undefined antes de poder teste para não null:

Correto :

if (typeof myObj !== "undefined" && myObj !== null) 

Experimente você mesmo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Objects</h2>

<p>If you want to test if an object is not null, you must test if it not undefined first.</p>

<p id="demo"></p>

<script>
document.getElementById("demo").innerHTML = typeof myObj !== "undefined" && myObj !== null;
</script>

</body>
</html>