Skip to content
This page has been auto-translated and may contain errors.View in English

Operadores e comparações

docs.scrimba.com

Digamos que você está rastreando um carrinho de compras. Você soma os preços, aplica um desconto, verifica se o total ultrapassa um limite de frete grátis e decide se deve mostrar um aviso quando o carrinho está vazio. Cada uma dessas etapas é um operador em ação: um símbolo que pega um ou dois valores e produz um novo. Este capítulo cobre os operadores que você usa constantemente, desde fazer aritmética em números até comparar valores e combinar testes verdadeiro-ou-falso.

Aritmética e atribuição

Os operadores aritméticos fazem a matemática que você já conhece: + soma, - subtrai, * multiplica, / divide. Existe um mais que você pode não ter encontrado: %, o operador de resto, que lhe dá o que sobra após uma divisão.

js
const total = 8 + 5; // 13
const change = 20 - 13; // 7
const leftover = 17 % 5; // 2, porque 5 cabe em 17 três vezes com 2 restantes
console.log(total); // 13

Quando você quer atualizar um valor baseado nele mesmo, existe uma abreviatura. Em vez de escrever score = score + 10, você pode escrever score += 10. Significa a mesma coisa: pega o valor atual, adiciona 10, armazena o resultado de volta.

js
let score = 100;
score += 10; // score agora é 110
score -= 30; // score agora é 80
console.log(score); // 80

E para mover um número para cima ou para baixo por exatamente um, ++ e -- fazem isso em um único passo. count++ adiciona um, count-- tira um.

js
let lives = 3;
lives--; // lives agora é 2
console.log(lives); // 2

Os operadores aritméticos são +, -, *, / e %. Os quatro primeiros são familiares; % é o que vale uma segunda olhada. Ele retorna o resto de uma divisão, o que o torna a ferramenta padrão para verificações "isso é divisível uniformemente?" e para envolver um valor de volta dentro de um intervalo.

js
const isEven = 10 % 2; // 0, então 10 é par
const isOdd = 7 % 2; // 1, então 7 é ímpar
console.log(isEven); // 0

Atualizar um valor a partir dele mesmo é comum o suficiente para ter abreviaturas. Cada operador aritmético se combina com = para formar uma atribuição composta: +=, -=, *=, /=, %=. Então price *= 1.2 lê como "multiplique price por 1.2 e armazene de volta", economizando você de escrever price = price * 1.2.

js
let price = 40;
price *= 1.2; // adicione 20 porcento, price agora é 48
price -= 8; // price agora é 40
console.log(price); // 40

Para uma mudança de exatamente um, ++ e -- incrementam e decrementam no lugar. Eles leem claramente quando você está incrementando um contador, e você os verá constantemente.

js
let attempts = 0;
attempts++; // attempts agora é 1
console.log(attempts); // 1

Os operadores aritméticos têm poucas surpresas para os quatro básicos, então os dois que valem atenção real são % e a sobrecarga +. O operador de resto % retorna o que sobra após divisão de estilo inteiro, e mantém o sinal do operando esquerdo: -7 % 3 é -1, não 2, o que confunde pessoas que esperam um módulo matemático. É seu recurso para testes de divisibilidade e para envolver um índice de volta para um intervalo.

js
const remainder = 17 % 5; // 2
const negative = -7 % 3; // -1, o sinal segue o operando esquerdo
console.log(negative); // -1

O operador + é sobrecarregado: com dois números ele soma, mas se qualquer lado for uma string ele concatena, coagindo o outro lado para uma string. Essa regra única está por trás de toda uma classe de surpresas, então nomeie o que você tem antes de adicionar.

js
const sum = 5 + 3; // 8
const glued = "5" + 3; // "53", o 3 se tornou uma string
console.log(glued); // 53

Atribuição composta (+=, -=, *=, /=, %=) é a forma idiomática de atualizar uma ligação a partir dela mesma, e herda a mesma sobrecarga +: msg += count transforma count em string. Os operadores de incremento e decremento ++ e -- vêm em formas prefixo e sufixo que diferem no valor que a expressão retorna: x++ avalia para o valor antigo então incrementa, ++x incrementa então avalia para o novo. Em uma expressão que distinção morde, então mantenha-os em sua própria instrução onde a diferença não importa. Use let para qualquer coisa que você reatribua dessa maneira, já que ligações const não podem ser atualizadas.

js
let counter = 5;
const before = counter++; // before é 5, counter agora é 6
const after = ++counter; // after é 7, counter agora é 7
console.log(`${before} ${after}`); // 5 7
JunoAritmética e atribuição Os operadores de matemática são os que você espera, mais % para o resto após dividir. Quando você atualiza um valor a partir dele mesmo, recorra à abreviatura: score += 10 em vez de score = score + 10. E ++ ou -- empurra um número para cima ou para baixo por um. Levou um tempo para eu confiar nestes, mas é a mesma matemática escrita mais curta.
JunoAritmética e atribuição Cinco operadores aritméticos, e % para o resto é o que se sustenta em verificações de divisibilidade. Atribuição composta como price *= 1.2 atualiza um valor a partir dele mesmo em um movimento, e ++ ou -- avança por um. Use let para qualquer coisa que você planeje atualizar dessa maneira, já que uma const não pode ser reatribuída.
JunoAritmética e atribuição Duas coisas para manter afiadas: % mantém o sinal do operando esquerdo, então -7 % 3 é -1, e + concatena no momento em que qualquer lado for uma string. Prefixo versus sufixo ++ retornam valores diferentes, então mantenha-os em sua própria instrução onde não pode morder. O resto dos operadores aritméticos se comporta exatamente como você esperaria.

Comparações

Uma comparação faz uma pergunta sobre dois valores e responde com true ou false. Essas respostas verdadeiro-ou-falso são booleanos, e é isso que seu programa usa para tomar decisões mais tarde.

A comparação que você usará mais é ===, que pergunta "esses dois são exatamente iguais?"

js
const answer = 42;
console.log(answer === 42); // true
console.log(answer === 7); // false

Seu oposto é !==, que pergunta "esses dois são diferentes?" E para ordem existem <, >, <= e >=, que funcionam como em matemática: menor que, maior que, menor ou igual, maior ou igual.

js
const age = 18;
console.log(age >= 18); // true
console.log(age !== 21); // true

Sempre compare com ===, nunca ==. A versão com dois sinais de igual tem uma peculiaridade que surpreende as pessoas, e a versão com três sinais de igual faz o que você espera toda vez.

Uma comparação pega dois valores e retorna um booleano, true ou false. Esse booleano é a matéria-prima para as decisões que você escreverá em condicionais, então acertar a comparação importa.

Use === para igualdade e !== para desigualdade. Para ordenação existem <, >, <= e >=.

js
const stock = 3;
console.log(stock === 0); // false
console.log(stock > 0); // true
console.log(stock <= 5); // true

A razão para optar por === em vez de == é que não são o mesmo operador. === (igualdade estrita) compara tanto valor quanto tipo, retornando true apenas quando eles correspondem. == (igualdade frouxa) primeiro converte os dois lados para um tipo comum e depois compara, o que produz resultados que quase ninguém prevê.

js
console.log(0 == ""); // true, e raramente o que você quer
console.log("1" == 1); // true, a string se tornou um número
console.log("1" === 1); // false, tipos diferentes

Padrão para === e !== toda vez. Eles comparam sem converter, então você nunca tem que raciocinar sobre as regras de conversão. Salve == para ler código antigo, não para escrever código novo.

Uma comparação retorna um booleano, e os operadores se dividem em duas famílias: igualdade (===, !==) e relacional (<, >, <=, >=). Os relacionais são diretos em números. Os de igualdade são onde a verdadeira decisão vive, porque JavaScript lhe dá dois deles.

=== (igualdade estrita) retorna true apenas quando ambos os operandos compartilham um tipo e um valor, sem conversão. == (igualdade frouxa) executa um algoritmo de igualdade abstrata que força os operandos para um tipo comum primeiro, e as regras práticas valem a pena saber para poder ler código antigo: comparar um número e uma string converte a string para um número ("1" == 1 é true); comparar um booleano para qualquer coisa converte o booleano para um número primeiro (true == 1, false == 0); null == undefined é true mas nenhum dos dois iguala qualquer outra coisa; e NaN não iguala nada, nem mesmo a si mesmo.

js
console.log(0 == ""); // true, "" se torna 0
console.log("1" == 1); // true, "1" se torna 1
console.log(null == undefined); // true, um caso especial
console.log(NaN === NaN); // false, NaN nunca é igual a qualquer coisa

Use === e !==; trate == como conhecimento somente leitura. O resultado não é memorizar cada caminho de coerção, é contorná-los: igualdade estrita não tem coerção, então seu resultado lê direto dos operandos. O único lugar onde == merece uma menção é a verificação null == undefined, que alguns bancos de código usam propositalmente para capturar ambos os valores nulos de uma vez, mas os operadores nullish mais tarde neste capítulo fazem esse trabalho mais claramente.

JunoComparações Uma comparação faz uma pergunta sim-ou-não sobre dois valores e responde com true ou false. Use === para verificar igualdade, !== para "diferente", e <, >, <=, >= para ordem. Mantenha-se com === e pule ==, porque a versão dupla tem uma surpresa nela e a versão tripla se comporta.
JunoComparações Cada comparação lhe entrega um booleano, que é o combustível para as decisões que você escreve a seguir. === verifica valor e tipo juntos; == converte os lados primeiro e produz oddities como 0 == "" sendo true. Padrão para === e !== para você nunca raciocinar sobre conversão, e deixe == para ler código antigo.
JunoComparações Igualdade estrita compara tipo e valor sem coerção, então sua resposta lê direto dos operandos. Frouxa == executa um algoritmo de conversão atrás de você, que é por que "1" == 1 é true e NaN não iguala nada. Escreva === e !== e mantenha as regras de coerção como conhecimento somente leitura para código antigo.

Operadores lógicos e veracidade

Frequentemente você precisa combinar mais de uma comparação. Os operadores lógicos deixam você fazer isso: && (e), || (ou) e ! (não).

&& é true apenas quando ambos os lados são true. || é true quando pelo menos um lado é true. ! inverte um booleano para seu oposto.

js
const age = 20;
const hasTicket = true;
console.log(age >= 18 && hasTicket); // true, ambos são true
console.log(age < 13 || hasTicket); // true, um lado é o suficiente
console.log(!hasTicket); // false, invertido

Existe uma ideia relacionada chamada truthy e falsy. Em uma configuração verdadeiro-ou-falso, JavaScript trata alguns valores não-booleanos como se fossem false. Os valores falsy são false, 0, "" (uma string vazia), null, undefined e NaN. Tudo mais conta como truthy.

js
const name = "";
console.log(!name); // true, uma string vazia é falsy

Os operadores lógicos combinam valores booleanos: && (e) é true apenas quando ambos os operandos são true, || (ou) é true quando pelo menos um é, e ! (não) inverte um booleano único.

js
const loggedIn = true;
const isAdmin = false;
console.log(loggedIn && isAdmin); // false, ambos devem ser true
console.log(loggedIn || isAdmin); // true, um é o suficiente
console.log(!isAdmin); // true

Os operadores não param em booleanos reais, porque JavaScript classifica cada valor em truthy ou falsy. O conjunto falsy é curto e vale a pena memorizar: false, 0, "", null, undefined e NaN. Tudo mais é truthy, incluindo "0", "false" e qualquer string não-vazia. Isso é o que deixa você escrever uma verificação como !username para significar "nenhum nome de usuário foi inserido".

js
const username = "";
console.log(!username); // true, "" é falsy
console.log(Boolean("hello")); // true, uma string não-vazia é truthy

Os operadores lógicos são &&, || e !, e a percepção chave é que && e || não retornam um booleano. Eles curto-circuitam: cada um avalia o operando esquerdo, e só avalia o direito se precisar, então retorna um dos operandos reais, não um true ou false coagido.

a || b retorna a se a é truthy, caso contrário b. a && b retorna a se a é falsy, caso contrário b. Esse comportamento sustenta o conjunto falsy: false, 0, "", null, undefined e NaN são os seis valores falsy, e tudo mais é truthy.

js
const name = "";
const display = name || "Guest"; // "Guest", porque "" é falsy
const label = "Sofia" && "active"; // "active", esquerda é truthy então retorna a direita
console.log(display); // Guest

O truque padrão || tem uma aresta afiada, que é por isso ?? (coalescência nullish) existe. || volta sempre que o lado esquerdo é qualquer valor falsy, então 0 || 10 é 10 e "" || "n/a" é "n/a", mesmo quando 0 e "" eram entradas válidas que você queria manter. ?? volta apenas quando o lado esquerdo é null ou undefined, tratando 0 e "" como valores reais.

js
const count = 0;
console.log(count || 5); // 5, mas 0 era um valor real
console.log(count ?? 5); // 0, ?? só substitui null ou undefined

Quando você precisa escolher entre dois valores baseado em uma condição, uma comparação completa mais um ternário (condition ? whenTrue : whenFalse) é a forma de uma linha, por exemplo age >= 18 ? "adult" : "minor". Isso é uma prévia; o capítulo condicionais cobre isso e a instrução if completamente.

JunoOperadores lógicos e veracidade&& é "ambos", || é "qualquer um", e ! inverte um booleano. Além disso, JavaScript trata alguns valores como falsos: false, 0, "", null, undefined e NaN são os falsy, e tudo mais é truthy. Isso é o que deixa !name significar "nenhum nome foi dado".
JunoOperadores lógicos e veracidade&& precisa de ambos os lados true, || precisa de um, e ! inverte. Cada valor é também truthy ou falsy, e o conjunto falsy é pequeno o suficiente para memorizar: false, 0, "", null, undefined, NaN. Observe que "0" e "false" são strings, então ambos são truthy.
JunoOperadores lógicos e veracidade&& e || curto-circuitam e retornam um operando, não um booleano, que é por que name || "Guest" funciona como padrão. Esse padrão tem uma aresta: || substitui cada valor falsy, então use ?? quando 0 e "" são entradas que você quer manter. Os seis valores falsy são a história toda, então aprenda o conjunto e o resto cai.

Para onde os operadores vão daqui

Operadores são os verbos da linguagem: eles pegam os valores que você armazena e os transformam em resultados e decisões. Aritmética produz novos números, comparações produzem booleanos, e operadores lógicos combinam esses booleanos nas respostas sim-ou-não que seu programa age.

Esses booleanos não fazem muito por conta própria. O próximo passo é usá-los para direcionar seu código, executando um ramo quando uma verificação passa e outro quando falha, que é do que trata o capítulo condicionais. Se algum dos valores aqui pareceu nebuloso, o capítulo tipos de dados é onde números, strings e booleanos ganham seu tratamento completo.