
Oi, habrozhiteli! Este livro permitirá que você mergulhe profundamente no tópico, aprenda como escrever um código bonito e eficaz. Você aprenderá sobre sintaxe, seta e funções assíncronas, iterador, seqüências de caracteres padrão e escopo de blocos.
Marein Haverbeke - praticante. Adquira experiência e aprenda o idioma com vários exemplos através de exercícios e projetos de treinamento. Primeiro, você se familiarizará com a estrutura da linguagem JavaScript, gerenciando estruturas, funções e estruturas de dados, depois estudará o tratamento de erros e correções de bugs, a modularidade e a programação assíncrona e depois seguirá para a programação do navegador.
Revise este livro
Este livro está dividido em três grandes partes. Os 12 primeiros capítulos discutem a linguagem JavaScript. Os próximos sete capítulos são sobre navegadores e como o JavaScript é usado para programá-los. Por fim, dois capítulos são dedicados ao Node.js, outro ambiente de programação JavaScript.
Ao longo do livro, você encontrará cinco capítulos de projetos que descrevem exemplos maiores de programas, para que você possa sentir o gosto da programação real. Na ordem em que aparecerem, trabalharemos na criação de um robô de entrega, uma linguagem de programação, uma plataforma de jogos, um editor de gráficos raster e um site dinâmico.
A parte do idioma do livro começa com quatro capítulos que apresentarão a estrutura básica da linguagem JavaScript. Você aprenderá sobre estruturas de controle (como a palavra-chave while, que você já viu na introdução), funções (escrevendo seus próprios blocos de construção) e estruturas de dados. Depois disso, você pode escrever os programas mais simples. Além disso, os capítulos 5 e 6 descrevem como usar funções e objetos para escrever um código mais abstrato e controlar sua complexidade.
Após o capítulo do primeiro projeto, a parte do idioma do livro continuará - os capítulos seguintes são dedicados à detecção e correção de erros, expressões regulares (uma ferramenta importante para trabalhar com texto), modularidade (outra defesa contra a complexidade) e programação assíncrona (trabalhando com eventos que duram alguns hora). A primeira parte do livro é completada pelo capítulo do segundo rascunho.
A segunda parte, capítulos 13 a 19, descreve as ferramentas às quais um navegador habilitado para JavaScript tem acesso. Você aprenderá como exibir elementos na tela (capítulos 14 e 17), responder à entrada do usuário (capítulo 15) e compartilhá-los na rede (capítulo 18). Esta parte também contém dois capítulos de projetos.
Depois disso, o Node.js é descrito no capítulo 20 e um pequeno site é criado no capítulo 21 usando a ferramenta especificada.
Trecho. Soma com redução
Outra coisa comum que geralmente é feita com matrizes é calcular um único valor com base nelas. Um caso especial disso é o exemplo que já usamos com a soma de um conjunto de números. Outro exemplo é encontrar a fonte que contém mais caracteres.
Uma operação de ordem superior que implementa esse padrão é chamada abreviação (às vezes também chamada de convolução). Esta operação cria o valor obtendo repetidamente um elemento da matriz e combinando-o com o valor atual. Ao somar os números, começamos do zero e adicionamos cada elemento subsequente à soma.
Os parâmetros da função de redução, além da matriz, são uma função combinada e um valor inicial. Essa função é um pouco mais complicada do que filtrar e mapear, portanto, veja com mais atenção:
function reduce(array, combine, start) { let current = start; for (let element of array) { current = combine(current, element); } return current; } console.log(reduce([1, 2, 3, 4], (a, b) => a + b, 0));
O método padrão para trabalhar com matrizes de redução, que, obviamente, corresponde a essa função, possui conveniência adicional. Se a matriz contiver pelo menos um elemento, você poderá omitir o argumento de início. O método seleciona o primeiro elemento da matriz como o valor inicial e inicia a redução a partir do segundo elemento.
console.log([1, 2, 3, 4].reduce((a, b) => a + b));
Para usar reduzir (duas vezes) para encontrar a fonte com mais caracteres, podemos escrever algo como isto:
function characterCount(script) { return script.ranges.reduce((count, [from, to]) => { return count + (to — from); }, 0); } console.log(SCRIPTS.reduce((a, b) => { return characterCount(a) < characterCount(b) ? b : a; }));
A função characterCount reduz os intervalos atribuídos a essa fonte calculando a soma de seus tamanhos. Preste atenção ao uso da desestruturação na lista de parâmetros da função de redução. Em seguida, a segunda chamada para reduzir usa o resultado anterior para encontrar a fonte maior, comparando as duas fontes repetidamente e retornando a fonte maior.
A fonte Han tem mais de 89.000 caracteres atribuídos no padrão Unicode, tornando-o o maior sistema de gravação em nosso conjunto de dados. Han é uma fonte usada às vezes para textos em chinês, japonês e coreano. Suas línguas têm muitos caracteres comuns, embora sejam escritas de maneira diferente. O Unicode Consortium (localizado nos EUA) decidiu considerar esses caracteres como um único sistema de gravação para salvar os códigos de caracteres. Isso se chama Unificação Han e ainda é muito irritante para algumas pessoas.
Composabilidade
Vamos pensar: como poderíamos reescrever o exemplo anterior (encontrar a maior fonte) sem funções de ordem superior? O código a seguir não é muito pior.
let biggest = null; for (let script of SCRIPTS) { if (biggest == null || characterCount(biggest) < characterCount(script)) { biggest = script; } } console.log(biggest);
Apareceram várias ligações adicionais, e o programa se tornou quatro linhas a mais. Mas esse código ainda é bastante claro.
As funções de ordem superior começam a ser realmente úteis quando você precisa compor operações. Como exemplo, vamos escrever um código que calcule o ano médio de criação de fontes de idiomas vivos e mortos em um conjunto de dados.
function average(array) { return array.reduce((a, b) => a + b) / array.length; } console.log(Math.round(average( SCRIPTS.filter(s => s.living).map(s => s.year))));
Portanto, scripts de idiomas mortos no Unicode são, em média, mais antigos que scripts de idiomas vivos.
Estas não são estatísticas particularmente significativas ou surpreendentes. Mas você concorda que o código usado para calcular é fácil de ler. Isso pode ser imaginado como um transportador: começamos analisando todas as fontes, filtrando os vivos (ou mortos), tirando os anos de sua criação, calculando o valor médio e arredondando o resultado.
Este cálculo também pode ser representado como um ciclo grande.
let total = 0, count = 0; for (let script of SCRIPTS) { if (script.living) { total += script.year; count += 1; } } console.log(Math.round(total / count));
Mas neste código é mais difícil entender o que e como é calculado. E como os resultados intermediários não são apresentados como valores consistentes, muito mais trabalho teria que ser feito para separar algo como a média em uma função separada.
Em termos do que o computador realmente faz, essas duas abordagens também são fundamentalmente diferentes. O primeiro cria novas matrizes quando o filtro e o mapa são executados, enquanto o segundo calcula apenas alguns números, fazendo menos trabalho. Geralmente, você pode oferecer uma opção mais legível, mas se você precisar processar matrizes muito grandes e fazê-lo várias vezes, um estilo menos abstrato poderá fornecer ganho de velocidade adicional.
Strings e códigos de caracteres
Um uso de conjuntos de dados é determinar em qual fonte um determinado pedaço de texto é digitado. Vejamos um programa que faz isso.
Lembre-se de que para cada fonte existe uma matriz de intervalos de código de caracteres. Portanto, conhecendo o código do caractere, poderíamos usar a seguinte função para encontrar a fonte correspondente (se houver):
function characterScript(code) { for (let script of SCRIPTS) { if (script.ranges.some(([from, to]) => { return code >= from && code < to; })) { return script; } } return null; } console.log(characterScript(121));
O método some é outra função de ordem superior. Ele usa uma função de teste e relata se retorna true para qualquer elemento da matriz.
Mas como obtemos códigos de caracteres como uma string?
No capítulo 1, mencionei que no JavaScript, as strings são representadas como sequências de números de 16 bits. Estas são as chamadas unidades de código. Inicialmente, assumiu-se que, em Unicode, o código de caractere será colocado em um bloco (que fornece um pouco mais de 65.000 caracteres). Quando ficou claro que isso não era suficiente, muitos começaram a se opor à necessidade de usar mais memória para armazenar um caractere. Para resolver esse problema, o formato UTF-16 usado nas seqüências de caracteres JavaScript foi inventado. Nele, os caracteres mais comuns ocupam uma unidade de código de 16 bits e o restante - duas unidades de código.
Hoje é geralmente aceito que o UTF-16 foi uma má ideia. Parece ter sido criado para produzir erros. Você pode escrever facilmente um programa para o qual as unidades e os caracteres de código são um e o mesmo. E se o seu idioma nativo não usar caracteres que ocupem duas unidades de código, este programa funcionará bem. Porém, assim que alguém tentar usar esse programa para um alfabeto menos comum, por exemplo, para caracteres chineses, ele será interrompido imediatamente. Felizmente, após o surgimento dos emoticons, duas unidades de código começaram a ser usadas em todos os lugares para a codificação de caracteres, e o ônus de resolver esses problemas foi distribuído de maneira mais justa.
Infelizmente, operações óbvias com cadeias de JavaScript, como obter seu comprimento através da propriedade length e acessar seu conteúdo com colchetes, lidam apenas com unidades de código.

O método JavaScript charCodeAt não retorna o código completo dos caracteres, mas uma unidade de código. O método codePointAt que aparece mais tarde retorna o caractere Unicode completo. Então, podemos usar isso para obter caracteres de uma string. Mas o argumento passado para codePointAt ainda é um índice em uma sequência de unidades de código. Portanto, para iterar todos os caracteres de uma sequência, ainda precisamos resolver a questão de se uma ou duas unidades de código ocupam um caractere.
No capítulo anterior, mencionei que o loop for / of também pode ser usado para strings. Como o codePointAt, esse tipo de loop apareceu em um momento em que os programadores perceberam claramente os problemas do UTF-16. Quando você aplica esse loop a uma string, ele fornece caracteres reais, não unidades de código.

Se você possui um caractere (que é uma sequência de uma ou duas unidades de código), para obter seu código, você pode usar codePointAt (0).
Reconhecimento de texto
Temos uma função characterScript e uma maneira de enumerar corretamente os caracteres em um loop. O próximo passo é contar o número de caracteres pertencentes a cada fonte. Aqui precisamos de uma abstração de contagem:
function countBy(items, groupName) { let counts = []; for (let item of items) { let name = groupName(item); let known = counts.findIndex(c => c.name == name); if (known == -1) { counts.push({name, count: 1}); } else { counts[known].count++; } } return counts; } console.log(countBy([1, 2, 3, 4, 5], n => n > 2));
A função countBy aceita uma coleção (tudo o que pode ser classificado em um loop for / of) e uma função que calcula o nome do grupo para um determinado elemento. A função countBy retorna uma matriz de objetos, cada um dos quais contém o nome do grupo e o número de elementos encontrados para ele.
Esta função usa outro método de trabalhar com matrizes - findIndex. Este método é um pouco semelhante ao indexOf, mas, em vez de procurar um valor específico, encontra o primeiro valor para o qual a função especificada retorna verdadeira. Se o item não for encontrado, findIndex, como indexOf, retorna -1.
Usando countBy, podemos escrever uma função que informa quais fontes foram usadas nesta parte do texto.

A função conta primeiro os caracteres pelo nome da fonte, usando o characterScript para dar um nome a eles, e retorna a string “none” para caracteres que não pertencem a nenhuma fonte. O filtro de chamada remove a entrada "none" da matriz resultante, pois não estamos interessados nesses caracteres.
Para poder calcular porcentagens, primeiro precisamos obter o número total de caracteres pertencentes à fonte que podemos calcular usando o método de redução. Se nenhum desses caracteres for encontrado, a função retornará uma sequência específica. Caso contrário, ele converte os resultados da contagem em sequências legíveis usando o mapa e, em seguida, combina-os usando a junção.
Sumário
A capacidade de passar valores funcionais para outras funções é um aspecto muito útil do JavaScript. Isso permite criar funções que simulam cálculos com espaços. Posteriormente, ao chamar essas funções no código, essas "lacunas" são preenchidas com valores funcionais.
Para matrizes, existem vários métodos úteis de ordem superior. O método forEach pode ser usado para percorrer os elementos de uma matriz. O método filter retorna uma nova matriz que contém apenas elementos que satisfazem a condição da função predicativa. A conversão da matriz executando uma função para cada elemento é feita usando o mapa. Para combinar todos os elementos de uma matriz em um único valor, você pode usar reduzir. O método some verifica se algum elemento corresponde a uma determinada função predicativa. Finalmente, o método findIndex localiza a posição do primeiro elemento que corresponde ao predicado.
»Mais informações sobre o livro podem ser encontradas no
site do editor»
Conteúdo»
TrechoCupom de 25% para vendedores ambulantes -
JavaScriptApós o pagamento da versão impressa do livro, um livro eletrônico é enviado por e-mail.