Dia 4 — Strings
Aspas, concatenar e interpolar
Aspas, concatenar e interpolar
Texto em JavaScript tem três delimitadores: aspa simples, aspa dupla e crase. O conteúdo é o mesmo; o que muda é o que dá para fazer com ele dentro.
| Delimitador | Nome | Interpola? | Quando usar |
|---|---|---|---|
'texto' | aspa simples | não | texto sem nada especial |
"texto" | aspa dupla | não | texto que contém ', ou o contrário |
` texto ` | crase ou template literal | sim | texto com variável dentro |
A crase é a única que interpola: é o que elimina a concatenação com + na maioria dos casos.
Interpolação: a crase com ${}
Dentro da crase, ${ } aceita qualquer expressão — não só variável. O que está entre as chaves é avaliado como uma linha de código e o resultado entra no texto.
const nome = 'Ana'; const idade = 30; `Olá, ${nome}`; // 'Olá, Ana' `${nome} tem ${idade} anos`; `${nome} vai fazer ${idade + 1} anos`; `${nome.toUpperCase()}`; // chamada de método dentro
A crase também aceita texto de várias linhas sem \n, e é a forma usada para montar trecho de HTML e consulta de banco:
`linha um linha dois`;
Para escrever a crase com um ${} que não deve ser interpretado, escapa o cifrão: \${ }.
Concatenar com + e onde ele engana
Concatenar é juntar com +. Funciona, mas o + vira texto assim que encontra uma string, e a soma vai da esquerda para a direita — o tipo muda no meio da expressão.
'Soma: ' + 2 + 2; // 'Soma: 22': o texto engoliu a soma 'Soma: ' + (2 + 2); // 'Soma: 4' `Soma: ${2 + 2}`; // 'Soma: 4': a crase não tem o problema
Separar argumentos com vírgula dentro do console.log evita o problema inteiro: cada argumento é medido antes de virar texto, e nenhum converte o outro.
Medir o texto e escrever o que não se digita
.length devolve a quantidade de caracteres. É propriedade, não método: sem parênteses.
'JavaScript'.length; // 10 'Café'.length; // 4: o á com acento é um caractere ''.length; // 0 ' '.length; // 1: espaço conta ' o '.length; // 3
Com emoji o resultado passa do número de letras que o olho vê, porque um emoji costuma ocupar dois caracteres. Com acento não há problema: Café são quatro caracteres, quatro letras.
Escape tira o sentido especial do caractere seguinte. É a forma de escrever aspa, barra ou quebra de linha dentro do texto.
| Escape | O que é |
|---|---|
\n | quebra de linha |
\t | recuo, como a tecla Tab |
\\ | uma barra |
\' | aspa simples, dentro de aspa simples |
\" | aspa dupla, dentro de aspa dupla |
A crase aceita \n igual, mas não precisa dele: dá para escrever a quebra de linha direto, e é mais legível em texto longo.
String() e toString()
São as duas formas de transformar valor em texto. String() funciona com qualquer valor, inclusive null e undefined; toString() precisa de um valor que tenha o método.
String(42); // '42' String(null); // 'null' String(undefined); // 'undefined' String([1, 2]); // '1,2' (42).toString(); // '42' (42).toString(2); // '101010': 42 em binário (255).toString(16);// 'ff': 255 em hexadecimal
Os parênteses em (42).toString() não são exagero: sem eles, o ponto seria lido como ponto decimal e o código quebraria.
toString com argumento muda a base, e não tem equivalente em PHP — é a forma de ler número em binário, octal ou hexadecimal.
Concatenar com
+e interpolar com crase dão o mesmo resultado. A diferença é de manutenção: a crase deixa o texto inteiro numa linha, e o+espalha o texto em pedaços que alguém vai ter que remontar. A regra do curso é crase sempre que houver variável no meio.
Exemplo
'use strict'; // ============================================================ // AULA 1 - Aspas, concatenar e interpolar // // Texto em JavaScript tem três delimitadores: aspa simples, aspa // dupla e crase. A crase é a única que interpola, ou seja, coloca // o valor de uma variável dentro do texto sem concatenar. // ============================================================ // As três formas. O conteúdo é o mesmo; o que muda é o delimitador. const nome = 'Ana'; console.log('--- as três formas de escrever texto ---'); console.log('aspas simples: ' + 'Olá, ' + nome); // com o + console.log('aspas duplas: ' + "Olá, " + nome); // com o + console.log('crase com ${}: ' + `Olá, ${nome}`); // com o ${} // A crase aceita dentro do ${} qualquer expressão: variável, // conta, chamada de método, chamada de função. Isso é a // interpolação, e é o que economiza a concatenação com `+`. const idade = 30; const altura = 1.72; console.log(''); console.log('--- interpolação ---'); console.log(`${nome} tem ${idade} anos`); console.log(`${nome} vai fazer ${idade + 1} anos no mês que vem`); console.log(`metade de ${idade} é ${idade / 2}`); console.log(`${nome.toUpperCase()} mede ${altura.toFixed(2)} m`); // A crase também aceita texto de várias linhas, sem \n. É a forma // usada para montar trecho de HTML e consulta de banco. console.log(''); console.log('--- crase com várias linhas ---'); console.log(`linha um linha dois linha três`); // Concatenar com `+` funciona, mas o `+` vira texto assim que // encontra uma string: é por isso que 1 + 1 + '2' dá '22'. console.log(''); console.log('--- onde o + engana ---'); console.log('1 + 1 + "2" =', 1 + 1 + '2'); console.log('"2" + 1 + 1 =', '2' + 1 + 1); console.log('"Soma: " + 2 + 2 =', 'Soma: ' + 2 + 2, '(o texto engoliu a soma)'); console.log('"Soma: " + (2 + 2) =', 'Soma: ' + (2 + 2), '(os parênteses resolveram)'); console.log('`Soma: ${2 + 2}` =', `Soma: ${2 + 2}`, '(a crase não tem o problema)'); // .length é a quantidade de caracteres. Em texto com acento ou // emoji, o resultado passa do número de letras que o olho vê. console.log(''); console.log('--- medir o texto ---'); console.log('"JavaScript".length =', 'JavaScript'.length); console.log('"Café".length =', 'Café'.length, '(o a com acento conta como um caractere)'); console.log('"".length =', ''.length); console.log('" ".length =', ' '.length, '(espaço conta)'); console.log('" o ".length =', ' o '.length, 'caracteres, e o texto tem 3 visíveis'); // Escape: a barra antes do caractere tira o sentido especial dele. // \n quebra a linha, \t recua, \\ escreve uma barra, e \' e \" são // as aspas do mesmo tipo que abrem o texto. console.log(''); console.log('--- escape ---'); console.log('linha um\nlinha dois'); console.log('coluna um\tcoluna dois'); console.log("aspas simples: \\'isto entre aspas simples\\' precisa da barra antes"); console.log('barra: \\\\'); // String() e toString() são as duas formas de transformar valor em // texto. String() funciona com qualquer valor, inclusive null e // undefined; toString() precisa de um valor que tenha o método. console.log(''); console.log('--- transformar em texto ---'); console.log('String(42):', String(42)); console.log('String(true):', String(true)); console.log('String(null):', String(null)); console.log('String(undefined):', String(undefined)); console.log('String([1, 2]):', String([1, 2])); console.log('(42).toString():', (42).toString()); console.log('(42).toString(2):', (42).toString(2), '(42 em binário)'); console.log('(255).toString(16):', (255).toString(16), '(255 em hexadecimal)'); console.log('concatenar vira texto:', '' + 42, '|', 42 + '', '(o + vazio também resolve)');
Saída real
--- as três formas de escrever texto ---
aspas simples: Olá, Ana
aspas duplas: Olá, Ana
crase com ${}: Olá, Ana
--- interpolação ---
Ana tem 30 anos
Ana vai fazer 31 anos no mês que vem
metade de 30 é 15
ANA mede 1.72 m
--- crase com várias linhas ---
linha um
linha dois
linha três
--- onde o + engana ---
1 + 1 + "2" = 22
"2" + 1 + 1 = 211
"Soma: " + 2 + 2 = Soma: 22 (o texto engoliu a soma)
"Soma: " + (2 + 2) = Soma: 4 (os parênteses resolveram)
`Soma: ${2 + 2}` = Soma: 4 (a crase não tem o problema)
--- medir o texto ---
"JavaScript".length = 10
"Café".length = 4 (o a com acento conta como um caractere)
"".length = 0
" ".length = 1 (espaço conta)
" o ".length = 3 caracteres, e o texto tem 3 visíveis
--- escape ---
linha um
linha dois
coluna um coluna dois
aspas simples: \'isto entre aspas simples\' precisa da barra antes
barra: \\
--- transformar em texto ---
String(42): 42
String(true): true
String(null): null
String(undefined): undefined
String([1, 2]): 1,2
(42).toString(): 42
(42).toString(2): 101010 (42 em binário)
(255).toString(16): ff (255 em hexadecimal)
concatenar vira texto: 42 | 42 (o + vazio também resolve)
Os metodos de string que o aluno procura
Os métodos de string que o aluno procura
String é imutável: nenhum método muda o texto original. Todos devolvem uma string nova, e quem guarda o resultado é quem muda de verdade.
const original = 'texto'; const modificado = original.toUpperCase(); original; // 'texto' — continua igual modificado; // 'TEXTO' — este é o novo
Escrever 'texto'.toUpperCase(); sozinho não guarda nada. O método precisa ficar do lado direito de uma atribuição ou de um console.log.
Buscar
A diferença entre as duas famílias é esta: includes responde se o texto existe, e indexOf responde onde. A primeira devolve verdadeiro ou falso; a segunda devolve a posição, ou -1 quando não acha. Buscar texto no meio da string é o includes e o indexOf; startsWith e endsWith são os casos particulares de começo e fim.
| Método | Assinatura | Devolve |
|---|---|---|
includes | includes(busca: string, posicao?: number): boolean | true ou false |
indexOf | indexOf(busca: string, posicao?: number): number | a posição, ou -1 |
lastIndexOf | lastIndexOf(busca: string): number | a última ocorrência, ou -1 |
startsWith | startsWith(busca: string, posicao?: number): boolean | começa com a busca? |
endsWith | endsWith(busca: string, fim?: number): boolean | termina com a busca? |
A distinção que mais importa: indexOf devolve posição, includes devolve verdadeiro ou falso. Os dois respondem "existe?", mas só um responde "onde?".
indexOf devolve -1 quando não acha, e -1 é um número como outro — por isso a checagem é idx !== -1 ou idx >= 0, nunca só if (idx). Posição 0 é válida e é falsa no if.
Fatiar
| Método | Assinatura | Nota |
|---|---|---|
slice | slice(inicio?: number, fim?: number): string | aceita índice negativo |
substring | substring(inicio: number, fim?: number): string | inverte os limites se vierem trocados |
substr | substr(inicio: number, tamanho: number): string | antigo: conta tamanho, não fim |
charAt | charAt(posicao: number): string | um caractere, '' se não existe |
charCodeAt | charCodeAt(posicao: number): number | o código numérico do caractere |
O slice é o método do curso. Índice negativo conta de trás para frente: palavra.slice(-6) são as últimas 6 letras.
Fatiar string é o nome da operação, e o slice é o que faz: ele devolve o pedaço entre duas posições, sem mexer no original, aceitando índice negativo — palavra.slice(0, 4) para os quatro primeiros, palavra.slice(-6) para os seis últimos.
substring(4, 0) não dá string vazia: devolve do 0 ao 4, porque troca os limites. slice(4, 0) devolve '', porque respeita a ordem. substr está em modo de depreciação há anos e não deve entrar em código novo.
O fim nunca entra na conta: slice(0, 4) de 'JavaScript' é 'Java', com quatro caracteres.
charCodeAt devolve o número do caractere, e a aritmética com ele resolve o que fromCharCode faz: 'A'.charCodeAt(0) + 1 dá 66, o código de 'B'.
Transformar
| Método | Assinatura | Exemplo | |
|---|---|---|---|
trim | trim(): string | ' Ana '.trim() → 'Ana' | |
toUpperCase | toUpperCase(): string | 'ana'.toUpperCase() → 'ANA' | |
toLowerCase | toLowerCase(): string | 'ANA'.toLowerCase() → 'ana' | |
replace | `replace(busca: string | RegExp, troca: string): string` | substitui a primeira ocorrência |
replaceAll | replaceAll(busca: string, troca: string): string | substitui todas | |
repeat | repeat(quantidade: number): string | 'ab'.repeat(3) → 'ababab' | |
padStart | padStart(tamanho: number, preenchimento?: string): string | '7'.padStart(3, '0') → '007' | |
padEnd | padEnd(tamanho: number, preenchimento?: string): string | '7'.padEnd(3, '.') → '7..' |
replace com texto simples troca só a primeira ocorrência. 'banana'.replace('a', 'A') dá 'bAnana', não 'bAnAnA'. Para todas: replaceAll, ou replace com expressão regular em /g.
padStart preenche pela esquerda, padEnd pela direita. É a forma de alinhar número com zero à esquerda e número de casa com espaço à direita.
O encadeamento é o que torna esses métodos úteis, e a ordem conta:
entrada.trim().toLowerCase();
Cortar o espaço antes de mexer na caixa: ' Ana '.toLowerCase() deixa espaço intacto, ' Ana '.trim().toLowerCase() resolve.
Separar e juntar
São os dois lados da mesma operação: split quebra o texto e devolve array; join junta valores e devolve texto.
| Método | Assinatura | Nota | |
|---|---|---|---|
split | `split(separador: string | RegExp, limite?: number): string[]` | separador vazio separa cada caractere |
join | join(separador?: string): string | o inverso do split |
'2026-03-15'.split('-'); // ['2026', '03', '15'] ['2026', '03', '15'].join('/'); // '2026/03/15' 'abc'.split(''); // ['a', 'b', 'c'] ['Ana', 'Bia'].join(' e '); // 'Ana e Bia'
O join é o método mais útil dos dois no trabalho do dia a dia: separador ', ' para log, '/' para caminho, ' e ' para frase. E split é a base de todo tratamento de texto: validar e-mail, cortar data, montar lista de tags.
trim,toLowerCaseeincludesjuntos resolvem o problema que mais aparece em formulário: o campo chega com espaço nas pontas, com maiúscula erraticamente, e oincludessem cortar o espaço não acha nada. A ordem étrim(), depois caixa, depois busca.
Exemplo
'use strict'; // ============================================================ // AULA 2 - Os métodos de string que o aluno procura // // String é imutável: nenhum método muda o texto original. Todos // devolvem uma string nova, e quem guarda o resultado é quem muda // de verdade. Este exemplo cobre buscar, fatiar, transformar, // separar e juntar. // ============================================================ // BUSCAR: se existe, e onde está. indexOf devolve a posição ou -1; // includes devolve true ou false. console.log('--- buscar ---'); const email = '[email protected]'; console.log('email:', email); console.log('indexOf("@"):', email.indexOf('@')); console.log('indexOf("."):', email.indexOf('.'), '(o primeiro ponto)'); console.log('indexOf("+"):', email.indexOf('+'), '(-1 quando não acha)'); console.log('lastIndexOf("."):', email.lastIndexOf('.'), '(o último ponto)'); console.log('includes("@"):', email.includes('@')); console.log('includes(" "):', email.includes(' '), '(espaço em e-mail não existe)'); console.log('startsWith("ana"):', email.startsWith('ana')); console.log('endsWith(".br"):', email.endsWith('.br')); console.log('startsWith("souza", 4):', email.startsWith('souza', 4), '(o segundo argumento é a posição inicial)'); // FATIAR: slice, substring e substr. slice aceita índice negativo // (contar de trás para frente); substring troca os limites quando // eles chegam invertidos; substr é antigo e conta o tamanho. console.log(''); console.log('--- fatiar ---'); const palavra = 'JavaScript'; console.log('palavra:', palavra); console.log('slice(0, 4):', palavra.slice(0, 4)); console.log('slice(4):', palavra.slice(4), '(até o fim)'); console.log('slice(-6):', palavra.slice(-6), '(as últimas 6 letras)'); console.log('slice(4, -6):', palavra.slice(4, -6), '(do meio, sem a ponta)'); console.log('substring(4, 0):', palavra.substring(4, 0), '(inverteu: devolve do 0 ao 4)'); console.log('substring(0, 4):', palavra.substring(0, 4)); console.log('substr(4, 6):', palavra.substr(4, 6), '(antigo: começa em 4, 6 caracteres)'); console.log('charAt(0):', palavra.charAt(0)); console.log('charAt(99):', palavra.charAt(99), '(texto vazio quando não existe)'); console.log('charCodeAt(0):', palavra.charCodeAt(0), '(código do "J")'); console.log("'A'.charCodeAt(0) + 1 =", 'A'.charCodeAt(0) + 1, '(o código de "A" virando "B")'); // TRANSFORMAR: caixa, espaço, troca e repetição. Nenhum método // mexe no original: quem guarda o resultado é quem muda. console.log(''); console.log('--- transformar ---'); const entrada = ' Ana Souza '; console.log('como chegou:', JSON.stringify(entrada), '(com espaço dos dois lados)'); console.log('trim():', JSON.stringify(entrada.trim())); console.log('toUpperCase():', entrada.trim().toUpperCase()); console.log('toLowerCase():', 'JAVA'.toLowerCase()); console.log('replace("a", "A") só a primeira:', 'banana'.replace('a', 'A')); console.log('replace(/-/g, "+") todas:', 'a-b-c'.replace(/-/g, '+')); console.log('replaceAll("-", "+") todas:', 'a-b-c'.replaceAll('-', '+')); console.log('repeat(3):', 'ab'.repeat(3)); console.log('padStart(5, "0"):', '42'.padStart(5, '0')); console.log('padEnd(5, "0"):', '42'.padEnd(5, '0')); console.log("'7'.padStart(3, '0') =", '7'.padStart(3, '0'), '(zero à esquerda)'); console.log("'7'.padEnd(3, '.') =", '7'.padEnd(3, '.'), '(ponto à direita)'); // O original continua igual depois de todos esses métodos: é o // resultado novo que precisa ser guardado em uma variável. console.log(''); console.log('--- string é imutável ---'); const original = 'texto'; const modificado = original.toUpperCase(); console.log('original:', original, '| modificado:', modificado); // SEPARAR e JUNTAR: split vira array, join volta a ser texto. São // os dois lados da mesma operação. console.log(''); console.log('--- split e join ---'); const data = '2026-03-15'; console.log('data:', data); console.log('split("-"):', data.split('-')); console.log('quantidade de partes:', data.split('-').length); const partes = data.split('-'); console.log('ano:', partes[0], '| mês:', partes[1], '| dia:', partes[2]); console.log('join("/"):', partes.join('/')); console.log('join("-"):', partes.join('-')); console.log('split(""):', 'abc'.split(''), '(separa em cada caractere)'); console.log('join(" e "):', ['Ana', 'Bia'].join(' e ')); console.log('join(""):', ['a', 'b', 'c'].join(''), '(sem separador, junta tudo)'); // Um caso de uso que junta o dia: cortar o espaço, mexer na caixa // e conferir o que a pessoa digitou. console.log(''); console.log('--- trim e caixa juntos ---'); const campo = ' [email protected] '; const limpo = campo.trim().toLowerCase(); console.log('como chegou:', JSON.stringify(campo)); console.log('como saiu:', JSON.stringify(limpo)); console.log('tem @?', limpo.includes('@')); console.log('domínio:', limpo.slice(limpo.indexOf('@') + 1)); console.log('começa com Joao ou Ana?', limpo.startsWith('joao') || limpo.startsWith('ana')); console.log('só o nome, sem o domínio:', limpo.replace(/@.*/, ''));
Saída real
--- buscar --- email: [email protected] indexOf("@"): 9 indexOf("."): 3 (o primeiro ponto) indexOf("+"): -1 (-1 quando não acha) lastIndexOf("."): 20 (o último ponto) includes("@"): true includes(" "): false (espaço em e-mail não existe) startsWith("ana"): true endsWith(".br"): true startsWith("souza", 4): true (o segundo argumento é a posição inicial) --- fatiar --- palavra: JavaScript slice(0, 4): Java slice(4): Script (até o fim) slice(-6): Script (as últimas 6 letras) slice(4, -6): (do meio, sem a ponta) substring(4, 0): Java (inverteu: devolve do 0 ao 4) substring(0, 4): Java substr(4, 6): Script (antigo: começa em 4, 6 caracteres) charAt(0): J charAt(99): (texto vazio quando não existe) charCodeAt(0): 74 (código do "J") 'A'.charCodeAt(0) + 1 = 66 (o código de "A" virando "B") --- transformar --- como chegou: " Ana Souza " (com espaço dos dois lados) trim(): "Ana Souza" toUpperCase(): ANA SOUZA toLowerCase(): java replace("a", "A") só a primeira: bAnana replace(/-/g, "+") todas: a+b+c replaceAll("-", "+") todas: a+b+c repeat(3): ababab padStart(5, "0"): 00042 padEnd(5, "0"): 42000 '7'.padStart(3, '0') = 007 (zero à esquerda) '7'.padEnd(3, '.') = 7.. (ponto à direita) --- string é imutável --- original: texto | modificado: TEXTO --- split e join --- data: 2026-03-15 split("-"): [ '2026', '03', '15' ] quantidade de partes: 3 ano: 2026 | mês: 03 | dia: 15 join("/"): 2026/03/15 join("-"): 2026-03-15 split(""): [ 'a', 'b', 'c' ] (separa em cada caractere) join(" e "): Ana e Bia join(""): abc (sem separador, junta tudo) --- trim e caixa juntos --- como chegou: " [email protected] " como saiu: "[email protected]" tem @? true domínio: escola.edu.br começa com Joao ou Ana? true só o nome, sem o domínio: joao.silva