Javascript - O Guia Definitivo (6ª Edição) PDF
Document Details
Uploaded by WonderfulMossAgate9892
UFMG
2013
David Flanagan
Tags
Summary
Este é um guia definitivo sobre a linguagem JavaScript e as APIs relacionadas a navegadores web, abrangendo a 6ª edição e ECMAScript 5 e HTML5. Destinado a programadores experientes que desejam aprimorar seus conhecimentos em JavaScript e programação web.
Full Transcript
Ative suas páginas Web Ab ra ng 6ª e Ed rip EC...
Ative suas páginas Web Ab ra ng 6ª e Ed rip EC M iç t 5 AS ão & H c TM JavaScript L5 O guia definitivo David Flanagan F583j Flanagan, David JavaScript : o guia definitivo / David Flanagan ; tradução: João Eduardo Nóbrega Tortello ; revisão técnica: Luciana Nedel. – 6. ed. – Porto Alegre : Bookman, 2013. xviii, 1062 p. : il. ; 25 cm. ISBN 978-85-65837-19-4 1. Ciência da computação. 2. Linguagem de programação – JavaScript. I. Título. CDU 004.438JavaScript Catalogação na publicação: Natascha Helena Franz Hoppen – CRB 10/2150 Tradução: João Eduardo Nóbrega Tortello Revisão técnica: Luciana Nedel Doutora em Ciência da Computação pela École Polytechnique Fédérale de Lausanne, Suíça Professora adjunta do Instituto de Informática da UFRGS 2013 Obra originalmente publicada sob o título JavaScript: The Definitive Guide, 6E ISBN 978-0-596-80552-4 copyright © 2011, David Flanagan. Tradução para a língua portuguesa copyright © 2013, Bookman Companhia Editora Ltda., uma empresa do Grupo A Educação SA. Esta tradução é publicada e comercializada com a permissão da O'Reilly Media,Inc., detentora de todos os direitos de publicação e comercialização da obra. Capa: VS Digital, arte sobre capa original Preparação de original: Bianca Basile Gerente Editorial – CESA: Arysinha Jacques Affonso Editora responsável por esta obra: Mariana Belloli Editoração eletrônica: Techbooks Reservados todos os direitos de publicação, em língua portuguesa, à BOOKMAN EDITORA LTDA., uma empresa do GRUPO A EDUCAÇÃO S.A. Av. Jerônimo de Ornelas, 670 – Santana 90040-340 – Porto Alegre – RS Fone: (51) 3027-7000 Fax: (51) 3027-7070 É proibida a duplicação ou reprodução deste volume, no todo ou em parte, sob quaisquer formas ou por quaisquer meios (eletrônico, mecânico, gravação, fotocópia, distribuição na Web e outros), sem permissão expressa da Editora. Unidade São Paulo Av. Embaixador Macedo Soares, 10.735 – Pavilhão 5 – Cond. Espace Center Vila Anastácio – 05095-035 – São Paulo – SP Fone: (11) 3665-1100 Fax: (11) 3667-1333 SAC 0800 703-3444 – www.grupoa.com.br IMPRESSO NO BRASIL PRINTED IN BRAZIL O autor David Flanagan é programador e escritor. Seu site é http://davidflanagan.com. Outros de seus livros publicados pela O’Reilly incluem JavaScript Pocket Reference, The Ruby Programming Language e Java in a Nutshell. David é formado em ciência da computação e engenharia pelo Massachusetts Ins- titute of Technology. Mora com sua esposa e filhos na região noroeste do Pacífico, entre as cidades de Seattle, Washington, Vancouver e British Columbia. A capa O animal que aparece na capa da 6ª edição deste livro é um rinoceronte de Java. Todas as cinco es- pécies de rinoceronte são conhecidas por seu enorme tamanho, couro espesso como uma armadura, pés com três dedos e um ou dois chifres no focinho. O rinoceronte de Java, junto com o rinoceronte de Sumatra, é uma das duas espécies que vivem em florestas. Ele tem aparência semelhante ao rino- ceronte indiano, mas é menor e possui certas características diferenciadas (principalmente a textura da pele). Os rinocerontes são frequentemente retratados em pé, com seus focinhos na água ou na lama. Na verdade, muitas vezes eles podem ser encontrados exatamente assim. Quando não estão repousando em um rio, os rinocerontes cavam buracos profundos para chafurdar. Esses dois locais de descanso oferecem duas vantagens. Primeiramente, aliviam o animal do calor tropical e oferecem uma pro- teção contra moscas sugadoras de sangue. (O lodo que o chafurdar deixa na pele do rinoceronte também oferece certa proteção contra moscas.) Segundo, a lama e a água do rio ajudam a suportar o peso considerável desses animais enormes, aliviando o peso sobre suas pernas e costas. O folclore há muito tempo diz que o chifre do rinoceronte possui poderes mágicos e afrodisíacos, e que os seres humanos, ao conquistarem os chifres, também obtêm esses poderes. Esse é um dos motivos pelos quais os rinocerontes são alvos de caçadores. Todas as espécies de rinoceronte estão em perigo, e a população de rinocerontes de Java é a que está em estado mais precário. Existem menos de 100 desses animais. Houve um tempo em que os rinocerontes de Java podiam ser encontrados por todo o sudeste asiático, mas agora acredita-se que só existam na Indonésia e no Vietnã. A ilustração da capa é uma gravura do Dover Pictorial Archive do século XIX. A fonte usada na capa é Adobe ITC Garamond. A fonte do texto é Adobe Garamond Pro, a dos títulos é Myriad Pro Condensed e a do código é TheSansMono. Este livro é dedicado a todos que pregam a paz e se opõem à violência. Esta página foi deixada em branco intencionalmente. Prefácio Este livro abrange a linguagem JavaScript e as APIs JavaScript implementadas pelos navegadores Web. Eu o escrevi para os leitores com pelo menos alguma experiência prévia em programação que queiram aprender JavaScript e também para programadores que já utilizam JavaScript, mas querem aumentar seu conhecimento e realmente dominar a linguagem e a plataforma Web. Meu objetivo com este livro é documentar de forma ampla e definitiva a linguagem e a plataforma Java- Script. Como resultado, ele é grande e detalhado. Contudo, espero que sua leitura cuidadosa seja recompensadora e que o tempo investido nela seja facilmente recuperado em forma de uma maior produtividade ao programar. Este livro está dividido em quatro partes. A Parte I abrange a linguagem JavaScript em si. A Parte II abrange JavaScript do lado do cliente: as APIs JavaScript definidas por HTML5 e padrões relaciona- dos e implementados pelos navegadores Web. A Parte III é a seção de referência da linguagem básica e a Parte IV é a referência para JavaScript do lado do cliente. O Capítulo 1 inclui um esboço dos capítulos das partes I e II (consulte a Seção 1.1). Esta 6ª edição do livro abrange ECMAScript 5 (a versão mais recente da linguagem básica) e HTML5 (a versão mais recente da plataforma Web). Você vai encontrar material sobre ECMAScript 5 ao longo de toda a Parte I. O material novo sobre HTML5 aparece principalmente nos capítulos do final da Parte II, mas também em alguns outros capítulos. Os capítulos totalmente novos desta edição são: Capítulo 11, Subconjuntos e extensões de JavaScript; Capítulo 12, JavaScript do lado do servidor; Capítulo 19, A biblioteca jQuery; e Capítulo 22, APIs de HTML5. Os leitores das versões anteriores poderão notar que reescrevi completamente muitos dos capítulos para a 6ª edição deste livro. O núcleo da Parte I – os capítulos que abordam objetos, arrays, funções e classes – é totalmente novo e torna o livro compatível com os estilos e as melhores práticas de pro- gramação atuais. Da mesma forma, os principais capítulos da Parte II, como aqueles que abordam documentos e eventos, foram completamente atualizados. x Prefácio Um lembrete sobre pirataria Caso esteja lendo a versão digital deste livro pela qual você (ou sua empresa) não pagou (ou pegou em- prestado de alguém que não pagou), então provavelmente tem um exemplar pirateado ilegalmente. Es- crever a 6ª edição deste livro foi um trabalho de tempo integral e me ocupou mais de um ano. A única maneira pela qual sou pago por esse tempo é quando os leitores compram o livro. E a única maneira de poder arcar com as despesas de uma 7ª edição é receber pela 6ª. Eu não tolero pirataria, mas se você tem um exemplar pirateado, vá em frente e leia alguns capítulos. Penso que você vai considerar este livro uma fonte de informações valiosa sobre JavaScript, mais bem or- ganizada e de qualidade mais alta do que o material que poderá encontrar gratuitamente (e legalmente) na Web. Se concordar que esta é uma fonte valiosa de informações, então, por favor, pague o preço de aquisição de um exemplar legal (digital ou impresso) do livro. Por outro lado, se achar que este livro não vale mais do que as informações gratuitas da Web, então desfaça-se de seu exemplar pirateado e use as fontes de informação gratuitas. Convenções usadas neste livro Utilizo as seguintes convenções tipográficas neste livro: Itálico Utilizado para dar ênfase e para indicar o primeiro uso de um termo. Itálico também é usado para endereços de email, URLs e nomes de arquivo. Largura constante Utilizada em todo código JavaScript, listagens CSS e HTML, e de modo geral para tudo que seria digitado literalmente ao se programar. Itálico de largura constante Utilizado para nomes de parâmetros de função e de modo geral como espaço reservado para indicar um item que deve ser substituído por um valor real em seu programa. Exemplo de código Os exemplos deste livro estão disponíveis online. Você pode encontrá-los na página do livro, no site da editora: http://www.bookman.com.br Este livro está aqui para ajudá-lo em seu trabalho. De maneira geral, você pode usar os códigos em seus programas e documentação. Não é preciso entrar em contato com a editora para pedir permissão, a não ser que esteja reproduzindo uma parte significativa de código. Por exemplo, não é necessário permissão para escrever um programa que utilize vários trechos de código deste livro. Vender ou distribuir um CD-ROM com exemplos exige permissão. Responder a uma per- gunta mencionando este livro e citando um exemplo de código não exige permissão. Incorpo- Prefácio xi rar um volume significativo de código de exemplo deste livro na documentação de seu produto exige permissão. Se você utilizar código deste livro, eu apreciaria (mas não exijo) a referência. Uma referência normal- mente inclui título, autor, editora e ISBN. Por exemplo: “JavaScript: O Guia Definitivo, de David Flanagan (Bookman). Copyright 2011 David Flanagan, 978-85-65837-19-4”. Para mais detalhes sobre a política de reutilização de código da editora, consulte http://oreilly.com/ pub/a/oreilly/ask_tim/2001/codepolicy.html (em inglês). Se você achar que o uso dos exemplos não se enquadra na permissão dada aqui, entre em contato com a editora pelo endereço permission@oreilly. com. Errata e como entrar em contato* A editora O’Reilly mantém uma lista pública dos erros encontrados neste livro (em inglês). Você pode ver a lista e apresentar os erros que encontrar visitando a página do livro: http://oreilly.com/catalog/9780596805531 Para fazer comentários ou perguntas técnicas sobre este livro, envie email para: [email protected] Agradecimentos Muitas pessoas me ajudaram na criação deste livro. Gostaria de agradecer ao meu editor, Mike Lou- kides, por tentar me manter dentro da agenda e por seus comentários perspicazes. Agradeço também aos meus revisores técnicos: Zachary Kessin, que revisou muitos dos capítulos da Parte I, e Raffaele Cecco, que revisou o Capítulo 19 e o material sobre no Capítulo 21. A equipe de produção da O’Reilly fez seu excelente trabalho, como sempre: Dan Fauxsmith gerenciou o processo de pro- dução, Teresa Elsey foi a editora de produção, Rob Romano desenhou as figuras e Ellen Troutman Zaig criou o índice. Nesta era de comunicação eletrônica fácil, é impossível manter um registro de todos aqueles que nos influenciam e informam. Gostaria de agradecer a todos que responderam minhas perguntas nas listas de discussão es5, w3c e whatwg, e a todos que compartilharam online suas ideias sobre progra- mação com JavaScript. Desculpem não mencioná-los a todos pelo nome, mas é um prazer trabalhar em uma comunidade tão vibrante de programadores de JavaScript. * N. de E.: Comentários, dúvidas e sugestões relativos à edição brasileira desta obra podem ser enviadas para secretariaedi- [email protected] xii Prefácio Os editores, revisores e colaboradores das edições anteriores deste livro foram: Andrew Schulman, Angelo Sirigos, Aristotle Pagaltzis, Brendan Eich, Christian Heilmann, Dan Shafer, Dave C. Mi- tchell, Deb Cameron, Douglas Crockford, Dr. Tankred Hirschmann, Dylan Schiemann, Frank Willison, Geoff Stearns, Herman Venter, Jay Hodges, Jeff Yates, Joseph Kesselman, Ken Cooper, Larry Sullivan, Lynn Rollins, Neil Berkman, Nick Thompson, Norris Boyd, Paula Ferguson, Peter- -Paul Koch, Philippe Le Hegaret, Richard Yaker, Sanders Kleinfeld, Scott Furman, Scott Issacs, Shon Katzenberger, Terry Allen, Todd Ditchendorf, Vidur Apparao e Waldemar Horwat. Esta edição do livro foi significativamente reescrita e me manteve afastado de minha família por muitas madrugadas. Meu amor para eles e meus agradecimentos por suportarem minhas ausências. — David Flanagan (davidflanagan.com) Sumário 1 Introdução a JavaScript................................................................................................... 1 1.1 JavaScript básica 4 1.2 JavaScript do lado do cliente 8 Parte I JavaScript básica 2 Estrutura léxica............................................................................................................. 21 2.1 Conjunto de caracteres 21 2.2 Comentários 23 2.3 Literais 23 2.4 Identificadores e palavras reservadas 23 2.5 Pontos e vírgulas opcionais 25 3 Tipos, valores e variáveis................................................................................................ 28 3.1 Números 30 3.2 Texto 35 3.3 Valores booleanos 39 3.4 null e undefined 40 3.5 O objeto global 41 3.6 Objetos wrapper 42 3.7 Valores primitivos imutáveis e referências de objeto mutáveis 43 3.8 Conversões de tipo 44 3.9 Declaração de variável 51 3.10 Escopo de variável 52 4 Expressões e operadores................................................................................................ 56 4.1 Expressões primárias 56 4.2 Inicializadores de objeto e array 57 4.3 Expressões de definição de função 58 4.4 Expressões de acesso à propriedade 59 4.5 Expressões de invocação 60 xiv Sumário 4.6 Expressões de criação de objeto 60 4.7 Visão geral dos operadores 61 4.8 Expressões aritméticas 65 4.9 Expressões relacionais 70 4.10 Expressões lógicas 74 4.11 Expressões de atribuição 76 4.12 Expressões de avaliação 78 4.13 Operadores diversos 80 5 Instruções..................................................................................................................... 85 5.1 Instruções de expressão 86 5.2 Instruções compostas e vazias 86 5.3 Instruções de declaração 87 5.4 Condicionais 90 5.5 Laços 95 5.6 Saltos 100 5.7 Instruções diversas 106 5.8 Resumo das instruções JavaScript 110 6 Objetos....................................................................................................................... 112 6.1 Criando objetos 113 6.2 Consultando e configurando propriedades 117 6.3 Excluindo propriedades 121 6.4 Testando propriedades 122 6.5 Enumerando propriedades 123 6.6 Métodos getter e setter de propriedades 125 6.7 Atributos de propriedade 128 6.8 Atributos de objeto 132 6.9 Serializando objetos 135 6.10 Métodos de objeto 135 7 Arrays......................................................................................................................... 137 7.1 Criando arrays 137 7.2 Lendo e gravando elementos de array 138 7.3 Arrays esparsos 140 7.4 Comprimento do array 140 7.5 Adicionando e excluindo elementos de array 141 7.6 Iteração em arrays 142 7.7 Arrays multidimensionais 144 7.8 Métodos de array 144 7.9 Métodos de array de ECMAScript 5 149 7.10 Tipo do array 153 7.11 Objetos semelhantes a um array 154 7.12 Strings como arrays 156 Sumário xv 8 Funções...................................................................................................................... 158 8.1 Definindo funções 159 8.2 Chamando funções 161 8.3 Argumentos e parâmetros de função 166 8.4 Funções como valores 171 8.5 Funções como espaço de nomes 173 8.6 Closures 175 8.7 Propriedades de função, métodos e construtora 181 8.8 Programação funcional 186 9 Classes e módulos........................................................................................................ 193 9.1 Classes e protótipos 194 9.2 Classes e construtoras 195 9.3 Classes estilo Java em JavaScript 199 9.4 Aumentando classes 202 9.5 Classes e tipos 203 9.6 Técnicas orientadas a objeto em JavaScript 209 9.7 Subclasses 222 9.8 Classes em ECMAScript 5 232 9.9 Módulos 240 10 Comparação de padrões com expressões regulares....................................................... 245 10.1 Definindo expressões regulares 245 10.2 Métodos de String para comparação de padrões 253 10.3 O objeto RegExp 255 11 Subconjuntos e extensões de JavaScript....................................................................... 258 11.1 Subconjuntos de JavaScript 259 11.2 Constantes e variáveis com escopo 262 11.3 Atribuição de desestruturação 264 11.4 Iteração 267 11.5 Funções abreviadas 275 11.6 Cláusulas catch múltiplas 276 11.7 E4X: ECMAScript para XML 276 12 JavaScript do lado do servidor...................................................................................... 281 12.1 Scripts Java com Rhino 281 12.2 E/S assíncrona com o Node 288 xvi Sumário Parte II JavaScript do lado do cliente 13 JavaScript em navegadores Web.................................................................................. 299 13.1 JavaScript do lado do cliente 299 13.2 Incorporando JavaScript em HTML 303 13.3 Execução de programas JavaScript 309 13.4 Compatibilidade e interoperabilidade 317 13.5 Acessibilidade 324 13.6 Segurança 324 13.7 Estruturas do lado do cliente 330 14 O objeto Window......................................................................................................... 332 14.1 Cronômetros 332 14.2 Localização do navegador e navegação 334 14.3 Histórico de navegação 336 14.4 Informações do navegador e da tela 337 14.5 Caixas de diálogo 339 14.6 Tratamento de erros 342 14.7 Elementos de documento como propriedades de Window 342 14.8 Várias janelas e quadros 344 15 Escrevendo script de documentos................................................................................. 351 15.1 Visão geral do DOM 351 15.2 Selecionando elementos do documento 354 15.3 Estrutura de documentos e como percorrê-los 361 15.4 Atributos 365 15.5 Conteúdo de elemento 368 15.6 Criando, inserindo e excluindo nós 372 15.7 Exemplo: gerando um sumário 377 15.8 Geometria e rolagem de documentos e elementos 380 15.9 Formulários HTML 386 15.10 Outros recursos de Document 395 16 Escrevendo script de CSS.............................................................................................. 402 16.1 Visão geral de CSS 403 16.2 Propriedades CSS importantes 407 16.3 Script de estilos em linha 420 16.4 Consultando estilos computados 424 16.5 Escrevendo scripts de classes CSS 426 16.6 Escrevendo scripts de folhas de estilo 429 Sumário xvii 17 Tratando eventos........................................................................................................ 433 17.1 Tipos de eventos 435 17.2 Registrando rotinas de tratamento de evento 444 17.3 Chamada de rotina de tratamento de evento 448 17.4 Eventos de carga de documento 453 17.5 Eventos de mouse 454 17.6 Eventos de roda do mouse 459 17.7 Eventos arrastar e soltar 462 17.8 Eventos de texto 469 17.9 Eventos de teclado 472 18 Scripts HTTP................................................................................................................ 478 18.1 Usando XMLHttpRequest 481 18.2 HTTP por : JSONP 500 18.3 Comet com eventos Server-Sent 502 19 A biblioteca jQuery...................................................................................................... 509 19.1 Fundamentos da jQuery 510 19.2 Métodos getter e setter da jQuery 517 19.3 Alterando a estrutura de documentos 523 19.4 Tratando eventos com jQuery 526 19.5 Efeitos animados 537 19.6 Ajax com jQuery 544 19.7 Funções utilitárias 557 19.8 Seletores jQuery e métodos de seleção 560 19.9 Estendendo a jQuery com plug-ins 568 19.10 A biblioteca jQuery UI 571 20 Armazenamento no lado do cliente.............................................................................. 573 20.1 localStorage e sessionStorage 575 20.2 Cookies 579 20.3 Persistência de userData do IE 585 20.4 Armazenamento de aplicativo e aplicativos Web off-line 587 21 Mídia e gráficos em scripts........................................................................................... 599 21.1 Escrevendo scripts de imagens 599 21.2 Escrevendo scripts de áudio e vídeo 601 21.3 SVG: Scalable Vector Graphics (Gráficos Vetoriais Escaláveis) 608 21.4 Elementos gráficos em um 616 xviii Sumário 22 APIs de HTML5............................................................................................................ 652 22.1 Geolocalização 653 22.2 Gerenciamento de histórico 656 22.3 Troca de mensagens entre origens 661 22.4 Web Workers 665 22.5 Arrays tipados e ArrayBuffers 672 22.6 Blobs 676 22.7 A API Filesystem 684 22.8 Bancos de dados do lado do cliente 690 22.9 Web Sockets 697 Parte III Referência de JavaScript básica Referência de JavaScript básica............................................................................................. 703 Parte IV Referência de JavaScript do lado do cliente Referência de JavaScript do lado do cliente........................................................................... 843 Índice.................................................................................................................................1003 CAPÍTULO 1 Introdução a JavaScript JavaScript é a linguagem de programação da Web. A ampla maioria dos sites modernos usa JavaScript e todos os navegadores modernos – em computadores de mesa, consoles de jogos, tablets e smartphones – incluem interpretadores JavaScript, tornando-a a linguagem de programação mais onipresente da história. JavaScript faz parte da tríade de tecnologias que todos os desenvolvedores Web devem conhecer: HTML, para especificar o conteúdo de páginas Web; CSS, para especificar a apresentação dessas páginas; e JavaScript, para especificar o comportamento delas. Este livro o ajudará a dominar a linguagem. Se você já conhece outras linguagens de programação, talvez ajude saber que JavaScript é uma lin- guagem de alto nível, dinâmica, interpretada e não tipada, conveniente para estilos de programação orientados a objetos e funcionais. A sintaxe de JavaScript é derivada da linguagem Java, das funções de primeira classe de Scheme e da herança baseada em protótipos de Self. Mas não é preciso co- nhecer essas linguagens nem estar familiarizado com esses termos para utilizar este livro e aprender JavaScript. Na verdade, o nome “JavaScript” é um pouco enganoso. A não ser pela semelhança sintática superfi- cial, JavaScript é completamente diferente da linguagem de programação Java. E JavaScript já deixou para trás suas raízes como linguagem de script há muito tempo, tornando-se uma linguagem de uso geral robusta e eficiente. A versão mais recente da linguagem (veja o quadro) define novos recursos para desenvolvimento de software em grande escala. 2 Capítulo 1 Introdução a JavaScript JavaScript: nomes e versões JavaScript foi criada na Netscape na fase inicial da Web e, tecnicamente, “JavaScript” é marca registra- da, licenciada pela Sun Microsystems (agora Oracle), usada para descrever a implementação da lingua- gem pelo Netscape (agora Mozilla). A Netscape enviou a linguagem para a ECMA – European Computer Manufacturer’s Association – para padronização e, devido a questões relacionadas à marca registrada, a versão padronizada manteve o nome estranho “ECMAScript”. Pelos mesmos motivos ligados à marca registrada, a versão da Microsoft da linguagem é formalmente conhecida como “JScript”. Na prática, quase todo mundo chama a linguagem de JavaScript. Este livro usa o nome “ECMAScript” apenas para se referir ao padrão da linguagem. Na última década, todos os navegadores Web implementaram a versão 3 do padrão ECMAScript e não havia necessidade de se pensar em números de versão: o padrão da linguagem era estável e as im- plementações dos navegadores eram, na maioria, interoperáveis. Recentemente, uma importante nova versão da linguagem foi definida como ECMAScript versão 5 e, quando este livro estava sendo produ- zido, os navegadores estavam começando a implementá-la. Este livro aborda todos os novos recursos da ECMAScript 5, assim como todos os recursos consagrados da ECMAScript 3. Às vezes, você vai ver essas versões da linguagem abreviadas como ES3 e ES5, assim como às vezes vai ver o nome JavaScript abreviado como JS. Quando falamos da linguagem em si, os únicos números de versão relevantes são ECMAScript versões 3 ou 5. (A versão 4 da ECMAScript esteve em desenvolvimento por anos, mas se mostrou ambiciosa demais e nunca foi lançada.) Contudo, às vezes você também vai ver um número de versão de JavaScript, como JavaScript 1.5 ou JavaScript 1.8. Esses são números da versão do Mozilla: a versão 1.5 é basicamente a ECMAScript 3 e as versões posteriores incluem extensões não padronizadas da linguagem (consulte o Capítulo 11). Por fim, também existem números de versão vinculados a interpretadores ou “engines” de JavaScript específicos. O Google chama seu interpretador JavaScript de V8, por exemplo, e quando este livro estava sendo produzido a versão corrente do mecanismo V8 era a 3.0. Para ser útil, toda linguagem deve ter ou uma plataforma, ou biblioteca padrão, ou API de funções para fazer coisas como entrada e saída básicas. A linguagem JavaScript básica define uma API mí- nima para trabalhar com texto, arrays, datas e expressões regulares, mas não inclui funcionalidade alguma de entrada ou saída. Entrada e saída (assim como recursos mais sofisticados, como conexão em rede, armazenamento e gráficos) são responsabilidade do “ambiente hospedeiro” dentro do qual JavaScript está incorporada. Normalmente, esse ambiente hospedeiro é um navegador Web (apesar de que iremos ver duas utilizações de JavaScript sem um navegador Web, no Capítulo 12). A Parte I deste livro aborda a linguagem em si e sua API interna mínima. A Parte II explica como JavaScript é usada em navegadores Web e aborda as amplas APIs baseadas em navegador, geralmente conhecidas como “JavaScript do lado do cliente”. A Parte III é a seção de referência da API básica. Você pode ler sobre a API de manipulação de arrays de JavaScript procurando por “Array” nessa parte do livro, por exemplo. A Parte IV é a seção de re- Capítulo 1 Introdução a JavaScript 3 ferência de JavaScript do lado do cliente. Você pode procurar por “Canvas” nessa parte do livro para ler sobre a API gráfica definida pelo elemento de HTML5, por exemplo. Este livro abrange inicialmente os fundamentos de nível mais baixo e depois os amplia para abs- trações mais avançadas e de nível mais alto. Os capítulos se destinam a serem lidos mais ou menos em ordem. Porém, aprender uma nova linguagem de programação nunca é um processo linear, e a descrição de uma linguagem também não é linear: cada recurso da linguagem se relaciona a outros recursos e este livro está repleto de referências cruzadas – às vezes para trás e às vezes à frente do ma- terial que você ainda não leu. Este capítulo faz um giro rápido pela linguagem básica e pela API do lado do cliente, apresentando recursos importantes que tornarão mais fácil entender o tratamento aprofundado dos capítulos seguintes. Explorando JavaScript Ao se aprender uma nova linguagem de programação é importante testar os exemplos do livro e, então, modificá-los e testá-los novamente para avaliar seu entendimento da linguagem. Para isso, você precisa de um interpretador de JavaScript. Felizmente, todo navegador Web contém um interpretador de Java- Script e, se você está lendo este livro, provavelmente já tem mais de um navegador Web instalado em seu computador. Ainda neste capítulo, vamos ver que é possível incorporar código JavaScript entre marcas em arquivos HTML e, quando o navegador carregar o arquivo, vai executar o código. Felizmente, contudo, não é preciso fazer isso sempre que você quiser testar trechos simples de código JavaScript. Impulsionados pela poderosa e inovadora extensão Firebug do Firefox (ilustrada na Figura 1-1 e disponível para down- load no endereço http://getfirebug.com/), todos os navegadores Web atuais contêm ferramentas para desenvolvedores Web que são indispensáveis para depuração, experimentação e aprendizado. Normal- mente, essas ferramentas podem ser encontradas no menu Ferramentas do navegador, sob nomes como “Desenvolvedor Web” ou “Console da Web”. (O Firefox contém um “Console da Web” interno, mas quando este livro estava sendo produzido, a extensão Firebug era melhor.) Frequentemente, é possível ativar um console com um toque de tecla, como F12 ou Ctrl-Shift-J. Muitas vezes, essas ferramentas de console apa- recem como painéis na parte superior ou inferior da janela do navegador, mas alguns permitem abri-las como janelas separadas (conforme ilustrado na Figura 1-1), o que costuma ser bastante conveniente. Um painel ou janela típica de “ferramentas para o desenvolvedor” contém várias guias que permitem ins- pecionar coisas como a estrutura de documentos HTML, estilos CSS, pedidos da rede, etc. Uma das guias é um “console JavaScript” que permite digitar linhas de código JavaScript e testá-las. Essa é uma maneira especialmente fácil de estudar JavaScript e recomendo que você a utilize ao ler este livro. Existe uma API de console simples, implementada de forma portável pelos navegadores modernos. Você pode usar a função console.log() para exibir texto na console. Isso muitas vezes é surpreendentemente útil ao se fazer depuração, sendo que alguns exemplos deste livro (mesmo na seção de linguagem básica) utilizam console.log() para produzir saída simples. Uma maneira semelhante, porém mais invasiva, de exibir saída ou mensagens de depuração é passar uma string de texto para a função alert(), a qual as exibe em uma caixa de diálogo modal. 4 Capítulo 1 Introdução a JavaScript Figura 1-1 Console de depuração Firebug do Firefox. 1.1 JavaScript básica Esta seção faz um giro pela linguagem JavaScript e também pela Parte I deste livro. Após este capítu- lo introdutório, entraremos no nível mais baixo de JavaScript: o Capítulo 2, Estrutura léxica, explica coisas como comentários em JavaScript, pontos e vírgulas e o conjunto de caracteres Unicode. O Capítulo 3, Tipos, valores e variáveis, começa a ficar mais interessante: ele explica as variáveis de Java- Script e os valores que podem ser atribuídos a elas. Aqui está um exemplo de código para ilustrar os destaques desses dois capítulos: // Tudo que vem após barras normais duplas é um comentário em linguagem natural. // Leia os comentários atentamente: eles explicam o código JavaScript. // variável é um nome simbólico para um valor. // As variáveis são declaradas com a palavra-chave var: var x; // Declara uma variável chamada x. // Valores podem ser atribuídos às variáveis com o sinal = x = 0; // Agora a variável x tem o valor 0 x // => 0: Uma variável é avaliada com seu valor. // JavaScript aceita vários tipos de valores x = 1; // Números. x = 0.01; // Apenas um tipo Number para inteiros e reais. x = "hello world"; // Strings de texto entre aspas. x = 'JavaScript'; // Apóstrofos também delimitam strings. x = true; // Valores booleanos. x = false; // O outro valor booleano. Capítulo 1 Introdução a JavaScript 5 x = null; // Null é um valor especial que significa "nenhum valor". x = undefined; // Undefined é como null. Dois outros tipos muito importantes que programas em JavaScript podem manipular são objetos e arrays. Esses são os temas do Capítulo 6, Objetos, e do Capítulo 7, Arrays, mas são tão importantes que você vai vê-los muitas vezes antes de chegar a esses capítulos. // O tipo de dados mais importante de JavaScript é o objeto. // Um objeto é uma coleção de pares nome/valor ou uma string para mapa de valores. var book = { // Objetos são colocados entre chaves. topic: "JavaScript", // A propriedade "topic" tem o valor "JavaScript". fat: true // A propriedade "fat" tem o valor true. }; // A chave marca o fim do objeto. // Acesse as propriedades de um objeto com. ou []: book.topic // => "JavaScript" book["fat"] // => true: outro modo de acessar valores de propriedade. book.author = "Flanagan"; // Crie novas propriedades por meio de atribuição. book.contents = {}; // {} é um objeto vazio sem qualquer propriedade. // JavaScript também aceita arrays (listas indexadas numericamente) de valores. var primes = [2, 3, 5, 7]; // Um array de 4 valores, delimitados com [ e ]. primes // => 2: o primeiro elemento (índice 0) do array. primes.lenght // => 4: quantidade de elementos no array. primes[primes.lenght-1] // => 7: o último elemento do array. primes = 9; // Adiciona um novo elemento por meio de atribuição. primes = 11; // Ou altera um elemento existente por meio de atribuição. var empty = []; // [] é um array vazio, sem qualquer elemento. empty.lenght // => 0 // Os arrays e objetos podem conter outros arrays e objetos: var points = [ // Um array com 2 elementos. {x:0, y:0}, // Cada elemento é um objeto. {x:1, y:1} ]; var data = { // Um objeto com 2 propriedades trial1: [[1,2], [3,4]], // O valor de cada propriedade é um array. trial2: [[2,3], [4,5]], // Os elementos dos arrays são arrays. }; A sintaxe ilustrada anteriormente para listar elementos de array entre chaves ou para mapear nomes de propriedade de objeto em valores de propriedade entre colchetes é conhecida como expressão ini- cializadora e é apenas um dos assuntos do Capítulo 4, Expressões e operadores. Uma expressão é uma frase em JavaScript que pode ser avaliada para produzir um valor. O uso de. e [] para se referir ao va- lor de uma propriedade de objeto ou a um elemento de array é uma expressão, por exemplo. Talvez você tenha notado no código anterior que, quando uma expressão aparece sozinha em uma linha, o comentário que se segue começa com uma seta (=>) e o valor da expressão. Essa é uma convenção que você vai ver por todo o livro. Uma das maneiras mais comuns de formar expressões em JavaScript é usar operadores, como segue: // Os operadores atuam sobre os valores (operandos) para produzir um novo valor. // Os operadores aritméticos são os mais comuns: 3 + 2 // => 5: adição 6 Capítulo 1 Introdução a JavaScript 3 – 2 // => 1: subtração 3 * 2 // => 6: multiplicação 3 / 2 // => 1.5: divisão points.x – points.x // => 1: operandos mais complicados também funcionam "3" + "2" // => "32": + soma números, ou concatena strings // JavaScript define alguns operadores aritméticos de forma abreviada var count = 0; // Define uma variável count++; // Incrementa a variável count--; // Decrementa a variável count += 2; // Soma 2: o mesmo que count = count + 2; count *= 3; // Multiplica por 3: o mesmo que count = count * 3; count // => 6: nomes de variáveis também são expressões. // Os operadores de igualdade e relacionais testam se dois valores são iguais, // desiguais, menores que, maiores que, etc. São avaliados como verdadeiros ou falsos. var x = 2, y = 3; // Esses sinais = são atribuições e não testes // de igualdade. x == y // => falso: igualdade x != y // => verdadeiro: desigualdade x < y // => verdadeiro: menor que x verdadeiro: menor ou igual a x > y // => falso: maior que x >= y // => falso: maior ou igual a "two" == "three" // => falso: as duas strings são diferentes "two" > "three" // => verdadeiro: "tw" é alfabeticamente maior do que "th" false == (x > y) // => verdadeiro: falso é igual a falso // Os operadores lógicos combinam ou invertem valores booleanos (x == 2) && (y == 3) // => verdadeiro: as duas comparações são verdadeiras. && // é E (x > 3) || (y < 3) // => falso: nenhuma das comparações é verdadeira. || é OU !(x == y) // => verdadeiro: ! inverte um valor booleano Se as frases em JavaScript são expressões, então as sentenças completas são instruções, as quais são o tema do Capítulo 5, Instruções. No código anterior, as linhas que terminam com ponto e vírgula são instruções. (No código a seguir, você vai ver instruções de várias linhas que não terminam com ponto e vírgula.) Na verdade há muita sobreposição entre instruções e expressões. Em linhas gerais, uma expressão é algo que calcula um valor, mas não faz nada: ela não altera o estado do programa de modo algum. As instruções, por outro lado, não têm um valor (ou não têm um valor com que nos preocupemos), mas alteram o estado. Você viu declarações de variável e instruções de atribuição anteriormente. A outra categoria abrangente de instrução são as estruturas de controle, como as con- dicionais e os laços. Exemplos aparecerão a seguir, após abordarmos as funções. Uma função é um bloco de código JavaScript nomeado e parametrizado que você define uma vez e, então, pode chamar repetidamente. As funções não serão abordadas formalmente até o Capítulo 8, Funções, mas, assim como os objetos e arrays, você vai vê-las muitas vezes antes de chegar a esse capítulo. Aqui estão alguns exemplos simples: // As funções são blocos de código JavaScript parametrizados que podemos chamar. function plus1(x) { // Define uma função chamada "plus1", com o parâmetro "x" return x+1; // Retorna um valor uma unidade maior do que o que foi passado } // As funções são incluídas entre chaves Capítulo 1 Introdução a JavaScript 7 plus1(y) // => 4: y é 3; portanto, essa chamada retorna 3+1 var square = function(x) { // As funções são valores e podem ser atribuídas a // variáveis return x*x; // Calcula o valor da função }; // Um ponto e vírgula marca o fim da atribuição. square(plus(y)) // => 16: chama duas funções em uma única expressão Quando combinamos funções com objetos, obtemos métodos: // Quando funções recebem as propriedades de um objeto, as // chamamos de "métodos". Todos os objetos de JavaScript têm métodos: var a = []; // Cria um array vazio a.push(1,2,3); // O método push() adiciona elementos em um array a.reverse(); // Outro método: inverte a ordem dos elementos // Também podemos definir nossos próprios métodos. A palavra-chave "this" se refere ao // objeto no qual o método é definido: neste caso, o array de pontos anterior. points.dist = function() { // Define um método para calcular a distância entre // pontos var p1 = this; // Primeiro elemento do array que chamamos var p2 = this; // Segundo elemento do objeto "this" var a = p2.x-p1.x; // Diferença em coordenadas X var b = p2.y-p1.y; // Diferença em coordenadas Y return Math.sqrt(a*a + // O teorema de Pitágoras b*b); // Math.sqrt() calcula a raiz quadrada }; points.dist() // => 1,414: distância entre nossos 2 pontos Agora, conforme prometido, aqui estão algumas funções cujos corpos demonstram instruções de estruturas de controle JavaScript comuns: // As instruções JavaScript incluem condicionais e laços que usam a sintaxe // das linguagens C, C++, Java e outras. function abs(x) { // Uma função para calcular o valor absoluto if (x >= 0) { // A instrução if... return x; // executa este código, se a comparação for // verdadeira. } // Este é o fim da cláusula if. else { // A cláusula opcional else executa seu código se return -x; // a comparação for falsa. } // Chaves são opcionais quando há 1 instrução por // cláusula. } // Observe as instruções return aninhadas dentro de // if/else. function factorial(n) { // Uma função para calcular fatoriais var product = 1; // Começa com o produto de 1 while(n > 1) { // Repete as instruções que estão em {}, enquanto a // expressão em () for verdadeira product *= n; // Atalho para product = product * n; n--; // Atalho para n = n – 1 } // Fim do laço return product; // Retorna o produto } factorial(4) // => 24: 1*4*3*2 8 Capítulo 1 Introdução a JavaScript function factorial2(n) { // Outra versão, usando um laço diferente var i, product = 1; // Começa com 1 for(i=2; i 120: 1*2*3*4*5 JavaScript é uma linguagem orientada a objetos, mas é bastante diferente da maioria. O Capítulo 9, Classes e módulos, aborda com detalhes a programação orientada a objetos em JavaScript, com mui- tos exemplos, sendo um dos capítulos mais longos do livro. Aqui está um exemplo muito simples que demonstra como definir uma classe JavaScript para representar pontos geométricos bidimen- sionais. Os objetos que são instâncias dessa classe têm um único método chamado r() que calcula a distância do ponto a partir da origem: // Define uma função construtora para inicializar um novo objeto Point function Point(x,y) { // Por convenção, as construtoras começam com letras // maiúsculas this.x = x; // A palavra-chave this é o novo objeto que está sendo // inicializado this.y = y; // Armazena os argumentos da função como propriedades do // objeto } // Nenhum return é necessário // Usa uma função construtora com a palavra-chave "new" para criar instâncias var p = new Point(1, 1); // O ponto geométrico (1,1) // Define métodos para objetos Point atribuindo-os ao objeto // prototype associado à função construtora. Point.prototype.r = function() { return Math.sqrt( // Retorna a raiz quadrada de x2 + y2 this.x * this.x + // Este é o objeto Point no qual o método... this.y * this.y //...é chamado. ); }; // Agora o objeto Point b (e todos os futuros objetos Point) herda o método r() p.r() // => 1,414... O Capítulo 9 é o clímax da Parte I e os capítulos posteriores resumem outros pontos e encerram nossa exploração da linguagem básica. O Capítulo 10, Comparação de padrões com expressões regu- lares, explica a gramática das expressões regulares e demonstra como utilizá-las na comparação de padrões textuais. O Capítulo 11, Subconjuntos e extensões de JavaScript, aborda os subconjuntos e as extensões de JavaScript básica. Por fim, antes de mergulharmos em JavaScript do lado do cliente em navegadores Web, o Capítulo 12, JavaScript do lado do servidor, apresenta duas maneiras de usar JavaScript fora dos navegadores. 1.2 JavaScript do lado do cliente JavaScript do lado do cliente não apresenta o problema de referência cruzada não linear no mesmo grau que a linguagem básica exibe, sendo que é possível aprender a usar JavaScript em navegado- res Web em uma sequência bastante linear. Porém, você provavelmente está lendo este livro para Capítulo 1 Introdução a JavaScript 9 aprender JavaScript do lado do cliente e a Parte II está muito longe daqui; portanto, esta seção é um esboço rápido das técnicas básicas de programação no lado do cliente, seguida por um exemplo detalhado. O Capítulo 13, JavaScript em navegadores Web, é o primeiro capítulo da Parte II e explica em detalhes como trabalhar com JavaScript em navegadores Web. O mais importante que você vai aprender nesse capítulo é que pode incorporar código JavaScript em arquivos HTML usando a marca : This is a paragraph of HTML // E este é um código JavaScript do lado do cliente // literalmente incorporado no arquivo HTML Here is more HTML. O Capítulo 14, O objeto Window, explica técnicas de scripts no navegador Web e aborda algumas funções globais importantes de JavaScript do lado do cliente. Por exemplo: function moveon() { // Exibe uma caixa de diálogo modal para fazer uma pergunta ao usuário var answer = confirm("Ready to move on?"); // Se ele clicou no botão "OK", faz o navegador carregar uma nova página if (answer) window.location = "http://google.com"; } // Executa a função definida acima por 1 minuto (60.000 milissegundos) a partir de agora. setTimeout(moveon, 60000); Note que o código do exemplo no lado do cliente mostrado nesta seção aparece em trechos mais lon- gos do que os exemplos da linguagem básica anteriormente no capítulo. Esses exemplos não devem ser digitados em uma janela de console do Firebug (ou similar). Em vez disso, você pode incorporá- -los em um arquivo HTML e testá-los, carregando-os em seu navegador Web. O código anterior, por exemplo, funciona como um arquivo HTML independente. O Capítulo 15, Escrevendo scripts de documentos, trata do que é realmente JavaScript do lado do cliente, fazendo scripts de conteúdo de documentos HTML. Ele mostra como se seleciona elementos HTML específicos dentro de um documento, como se define os atributos HTML desses elementos, como se altera o conteúdo desses elementos e como se adiciona novos elementos no documento. A função a seguir demonstra diversas dessas técnicas básicas de pesquisa e modificação de documentos: // Exibe uma mensagem em uma seção de saída de depuração especial do documento. // Se o documento não contém esta seção, cria uma. function debug(msg) { // Localiza a seção de depuração do documento, examinando os atributos de // identificação HTML var log = document.getElementById("debuglog"); 10 Capítulo 1 Introdução a JavaScript // Se não existe elemento algum com a identificação "debuglog", cria um. if (!log) { log = document.createElement("div"); // Cria um novo elemento log.id = "debuglog"; // Define o atributo de identificação HTML // nele log.innerHTML = "Debug Log"; // Define o conteúdo inicial document.body.appendChild(log); // Adiciona-o no final do documento } // Agora, coloca a mensagem em seu próprio e a anexa no log var pre = document.createElement("pre"); // Cria uma marca var text = document.createTextNode(msg); // Coloca a msg em um nó de texto pre.appendChild(text); // Adiciona o texto no log.appendChild(pre); // Adiciona no log } O Capítulo 15 mostra como JavaScript pode fazer scripts de elementos HTML que definem con- teúdo da Web. O Capítulo 16, Scripts de CSS, mostra como você pode usar JavaScript com os estilos CSS que definem a apresentação desse conteúdo. Normalmente isso é feito com o atributo style ou class dos elementos HTML: function hide(e, reflow) { // Oculta o elemento e faz script de seu estilo if (reflow) { // Se o 2º argumento é verdadeiro e.style.display = "none" // oculta o elemento e utiliza seu espaço } else { // Caso contrário e.style.visibility = "hidden"; // torna e invisível, mas deixa seu espaço } } function highlight(e) { // Destaca e, definindo uma classe CSS // Basta definir ou anexar no atributo da classe HTML. // Isso presume que uma folha de estilos CSS já define a classe "hilite" if (!e.className) e.className = "hilite"; else e.className += " hilite"; } JavaScript nos permite fazer scripts do conteúdo HTML e da apresentação CSS de documentos em navegadores Web, mas também nos permite definir o comportamento desses documentos com roti- nas de tratamento de evento. Uma rotina de tratamento de evento é uma função JavaScript que regis- tramos no navegador e que este chama quando ocorre algum tipo de evento especificado. O evento de interesse pode ser um clique de mouse ou um pressionamento de tecla (ou, em um smartphone, pode ser um gesto de algum tipo, feito com dois dedos). Ou então, uma rotina de tratamento de evento pode ser ativada quando o navegador termina de carregar um documento, quando o usuário redimensiona a janela do navegador ou quando o usuário insere dados em um elemento de formulá- rio HTML. O Capítulo 17, Tratando eventos, explica como se define e registra rotinas de tratamento de eventos e como o navegador as chama quando ocorrem eventos. O modo mais simples de definir rotinas de tratamento de evento é com atributos HTML que co- meçam com “on”. A rotina de tratamento “onclick” é especialmente útil quando se está escrevendo programas de teste simples. Suponha que você tenha digitado as funções debug() e hide() anteriores e salvo em arquivos chamados debug.js e hide.js. Você poderia escrever um arquivo de teste simples em HTML usando elementos com atributos da rotina de tratamento de evento onclick: Capítulo 1 Introdução a JavaScript 11 Hello Hide1 Hide2 World Aqui está um código JavaScript do lado do cliente que utiliza eventos. Ele registra uma rotina de tratamento de evento para o importante evento “load” e também demonstra uma maneira mais sofisticada de registrar funções de rotina de tratamento para eventos “click”: // O evento "load" ocorre quando um documento está totalmente carregado. Normalmente, // precisamos esperar por esse evento antes de começarmos a executar nosso código // JavaScript. window.onload = function() { // Executa esta função quando o documento for carregado // Localiza todas as marcas no documento var images = document.getElementsByTagName("img"); // Faz um laço por elas, adicionando uma rotina de tratamento para eventos "click" em // cada uma para que clicar na imagem a oculte. for(var i = 0; i < images.length; i++) { var image = images[i]; if (image.addEventListener) // Outro modo de registrar uma rotina de // tratamento image.addEventListener("click", hide, false); else // Para compatibilidade com o IE8 e anteriores image.attachEvent("onclick", hide); } // Esta é a função de rotina para tratamento de evento registrada anteriormente function hide(event) { event.target.style.visibility = "hidden"; } }; Os capítulos 15, 16 e 17 explicam como usar JavaScript para fazer scripts do conteúdo (HTML), da apresentação (CSS) e do comportamento (tratamento de eventos) de páginas Web. As APIs des- critas nesses capítulos são um pouco complexas e, até recentemente, cheias de incompatibilidades com os navegadores. Por esses motivos, a maioria dos programadores JavaScript do lado do cliente optam por usar uma biblioteca ou estrutura do lado do cliente para simplificar as tarefas básicas de programação. A biblioteca mais popular é a jQuery, o tema do Capítulo 19, A biblioteca jQuery. A biblioteca jQuery define uma API engenhosa e fácil de usar para fazer scripts do conteúdo, da apre- sentação e do comportamento de documentos. Ela foi completamente testada e funciona em todos os principais navegadores, inclusive nos antigos, como o IE6. É fácil identificar um código jQuery, pois ele utiliza frequentemente uma função chamada $(). Aqui está a função debug() utilizada anteriormente, reescrita com jQuery: function debug(msg) { var log = $("#debuglog"); // Localiza o elemento para exibir a msg. if (log.length == 0) { // Se ele ainda não existe, cria-o... log = $("Debug Log"); log.appendTo(document.body); // e o insere no final do corpo. } log.append($("").text(msg)); // Coloca a msg em e anexa no log. } 12 Capítulo 1 Introdução a JavaScript Os quatro capítulos da Parte II descritos até aqui foram todos sobre páginas Web. Outros quatro capítulos mudam o enfoque para aplicativos Web. Esses capítulos não falam sobre o uso de navega- dores Web para exibir documentos com conteúdo, apresentação e comportamento em scripts. Em vez disso, falam sobre o uso de navegadores Web como plataformas de aplicativo e descrevem as APIs fornecidas pelos navegadores modernos para suportar aplicativos Web sofisticados do lado do clien- te. O Capítulo 18, Scripts HTTP, explica como se faz requisições HTTP em scripts JavaScript – um tipo de API de ligação em rede. O Capítulo 20, Armazenamento no lado do cliente, descreve mecanis- mos para armazenar dados – e até aplicativos inteiros – no lado do cliente para usar em sessões de na- vegação futuras. O Capítulo 21, Mídia e gráficos em scripts, aborda uma API do lado do cliente para desenhar elementos gráficos em uma marca da HTML. E, por fim, o Capítulo 22, APIs de HTML5, aborda várias APIs de aplicativo Web novas, especificadas pela HTML5 ou relacionadas a ela. Conexão em rede, armazenamento, gráficos: esses são serviços de sistema operacional que estão sendo fornecidos pelos navegadores Web, definindo um novo ambiente de aplicativo independente de plataforma. Se você está visando navegadores que aceitam essas novas APIs, esse é um bom mo- mento para ser um programador JavaScript do lado do cliente. Não há exemplos de código desses quatro últimos capítulos aqui, mas o longo exemplo a seguir utiliza algumas dessas novas APIs. 1.2.1 Exemplo: uma calculadora de empréstimos em JavaScript Este capítulo termina com um longo exemplo que reúne muitas dessas técnicas e mostra como são os programas JavaScript do lado do cliente reais (mais HTML e CSS). O Exemplo 1-1 lista o código do aplicativo de calculadora de pagamento de empréstimos simples ilustrada na Figura 1-2. Figura 1-2 Um aplicativo Web de calculadora de empréstimos. Vale a pena examinar o Exemplo 1-1 atentamente. Não espere compreender tudo, mas o código está bastante comentado e você será capaz de pelo menos entender a ideia geral de seu funcionamento. O Capítulo 1 Introdução a JavaScript 13 exemplo demonstra vários recursos da linguagem JavaScript básica e também importantes técnicas de JavaScript do lado do cliente: Como localizar elementos em um documento. Como obter entrada do usuário a partir de elementos de entrada de formulários. Como definir o conteúdo HTML de elementos do documento. Como armazenar dados no navegador. Como fazer requisições HTTP em scripts. Como desenhar gráficos com o elemento. Exemplo 1-1 Uma calculadora de empréstimos em JavaScript JavaScript Loan Calculator.output { font-weight: bold; } #payment { text-decoration: underline; } #graph { border: solid black 1px; } th, td { vertical-align: top; } Enter Loan Data: Loan Balance, Cumulative Equity, and Interest Payments Amount of the loan ($): Annual interest (%): Repayment period (years): Zipcode (to find lenders): Approximate Payments: Calculate Monthly payment: $ Total payment: $ 14 Capítulo 1 Introdução a JavaScript Total interest: $ Sponsors: Apply for your loan with one of these fine lenders: "use strict"; // Usa o modo restrito da ECMAScript 5 nos navegadores que o suportam function calculate() { // Pesquisa os elementos de entrada e saída no documento var amount = document.getElementById("amount"); var apr = document.getElementById("apr"); var years = document.getElementById("years"); var zipcode = document.getElementById("zipcode"); var payment = document.getElementById("payment"); var total = document.getElementById("total"); var totalinterest = document.getElementById("totalinterest"); // Obtém a entrada do usuário através dos elementos de entrada. Presume que tudo isso // é válido. // Converte os juros de porcentagem para decimais e converte de taxa // anual para taxa mensal. Converte o período de pagamento em anos // para o número de pagamentos mensais. var principal = parseFloat(amount.value); var interest = parseFloat(apr.value) / 100 / 12; var payments = parseFloat(years.value) * 12; // Agora calcula o valor do pagamento mensal. var x = Math.pow(1 + interest, payments); // Math.pow() calcula potências var monthly = (principal*x*interest)/(x-1); // Se o resultado é um número finito, a entrada do usuário estava correta e // temos resultados significativos para exibir if (isFinite(monthly)) { // Preenche os campos de saída, arredondando para 2 casas decimais payment.innerHTML = monthly.toFixed(2); total.innerHTML = (monthly * payments).toFixed(2); totalinterest.innerHTML = ((monthly*payments)-principal).toFixed(2); // Salva a entrada do usuário para que possamos recuperá-la na próxima vez que // ele visitar save(amount.value, apr.value, years.value, zipcode.value); Capítulo 1 Introdução a JavaScript 15 // Anúncio: localiza e exibe financeiras locais, mas ignora erros de rede try { // Captura quaisquer erros que ocorram dentro destas chaves getLenders(amount.value, apr.value, years.value, zipcode.value); } catch(e) { } // Por fim, traça o gráfico do saldo devedor, dos juros e dos pagamentos do capital chart(principal, interest, monthly, payments); } else { // O resultado foi Not-a-Number ou infinito, o que significa que a entrada // estava incompleta ou era inválida. Apaga qualquer saída exibida anteriormente. payment.innerHTML = ""; // Apaga o conteúdo desses elementos total.innerHTML = "" totalinterest.innerHTML = ""; chart(); // Sem argumentos, apaga o gráfico } } // Salva a entrada do usuário como propriedades do objeto localStorage. Essas // propriedades ainda existirão quando o usuário visitar no futuro // Esse recurso de armazenamento não vai funcionar em alguns navegadores (o Firefox, por // exemplo), se você executar o exemplo a partir de um arquivo local:// URL. Contudo, // funciona com HTTP. function save(amount, apr, years, zipcode) { if (window.localStorage) { // Só faz isso se o navegador suportar localStorage.loan_amount = amount; localStorage.loan_apr = apr; localStorage.loan_years = years; localStorage.loan_zipcode = zipcode; } } // Tenta restaurar os campos de entrada automaticamente quando o documento é carregado // pela primeira vez. window.onload = function() { // Se o navegador suporta localStorage e temos alguns dados armazenados if (window.localStorage && localStorage.loan_amount) { document.getElementById("amount").value = localStorage.loan_amount; document.getElementById("apr").value = localStorage.loan_apr; document.getElementById("years").value = localStorage.loan_years; document.getElementById("zipcode").value = localStorage.loan_zipcode; } }; // Passa a entrada do usuário para um script no lado do servidor que (teoricamente) pode // retornar // uma lista de links para financeiras locais interessadas em fazer empréstimos. Este // exemplo não contém uma implementação real desse serviço de busca de financeiras. Mas // se o serviço existisse, essa função funcionaria com ele. function getLenders(amount, apr, years, zipcode) { // Se o navegador não suporta o objeto XMLHttpRequest, não faz nada if (!window.XMLHttpRequest) return; 16 Capítulo 1 Introdução a JavaScript // Localiza o elemento para exibir a lista de financeiras var ad = document.getElementById("lenders"); if (!ad) return; // Encerra se não há ponto de saída // Codifica a entrada do usuário como parâmetros de consulta em um URL var url = "getLenders.php" + // Url do serviço mais "?amt=" + encodeURIComponent(amount) + // dados do usuário na string // de consulta "&apr=" + encodeURIComponent(apr) + "&yrs=" + encodeURIComponent(years) + "&zip=" + encodeURIComponent(zipcode); // Busca o conteúdo desse URL usando o objeto XMLHttpRequest var req = new XMLHttpRequest(); // Inicia um novo pedido req.open("GET", url); // Um pedido GET da HTTP para o url req.send(null); // Envia o pedido sem corpo // Antes de retornar, registra uma função de rotina de tratamento de evento que será // chamada em um momento posterior, quando a resposta do servidor de HTTP chegar. // Esse tipo de programação assíncrona é muito comum em JavaScript do lado do // cliente. req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) { // Se chegamos até aqui, obtivemos uma resposta HTTP válida e completa var response = req.responseText; // Resposta HTTP como string var lenders = JSON.parse(response); // Analisa em um array JS // Converte o array de objetos lender em uma string HTML var list = ""; for(var i = 0; i < lenders.length; i++) { list += "" + lenders[i].name + ""; } // Exibe o código HTML no elemento acima. ad.innerHTML = "" + list + ""; } } } // Faz o gráfico do saldo devedor mensal, dos juros e do capital em um elemento // da HTML. // Se for chamado sem argumentos, basta apagar qualquer gráfico desenhado anteriormente. function chart(principal, interest, monthly, payments) { var graph = document.getElementById("graph"); // Obtém a marca graph.width = graph.width; // Mágica para apagar e redefinir o elemento // canvas // Se chamamos sem argumentos ou se esse navegador não suporta // elementos gráficos em um elemento , basta retornar agora. if (arguments.length == 0 || !graph.getContext) return; // Obtém o objeto "contexto" de que define a API de desenho var g = graph.getContext("2d"); // Todo desenho é feito com esse objeto var width = graph.width, height = graph.height; // Obtém o tamanho da tela de // desenho Capítulo 1 Introdução a JavaScript 17 // Essas funções convertem números de pagamento e valores monetários em pixels function paymentToX(n) { return n * width/payments; } function amountToY(a) { return height-(a * height/(monthly*payments*1.05));} // Os pagamentos são uma linha reta de (0,0) a (payments, monthly*payments) g.moveTo(paymentToX(0), amountToY(0)); // Começa no canto inferior esquerdo g.lineTo(paymentToX(payments), // Desenha até o canto superior direito amountToY(monthly*payments)); g.lineTo(paymentToX(payments), amountToY(0)); // Para baixo, até o canto // inferior direito g.closePath(); // E volta ao início g.fillStyle = "#f88"; // Vermelho-claro g.fill(); // Preenche o triângulo g.font = "bold 12px sans-serif"; // Define uma fonte g.fillText("Total Interest Payments", 20,20); // Desenha texto na legenda // O capital acumulado não é linear e é mais complicado de representar no gráfico var equity = 0; g.beginPath(); // Inicia uma nova figura g.moveTo(paymentToX(0), amountToY(0)); // começando no canto inferior // esquerdo for(var p = 1; p 1.0: arredonda para o inteiro mais próximo Math.ceil(.6) // => 1.0: arredonda para cima para um inteiro Math.floor(.6) // => 0.0: arredonda para baixo para um inteiro Math.abs(-5) // => 5: valor absoluto Math.max(x,y,z) // Retorna o maior argumento Math.min(x,y,z) // Retorna o menor argumento Math.random() // Número pseudoaleatório x, onde 0 verdadeiro: zero e zero negativo são iguais 1/zero === 1/negz // => falso: infinito e -infinito não são iguais 3.1.4 Ponto flutuante binário e erros de arredondamento Existem infinitos números reais, mas apenas uma quantidade finita deles (18437736874454810627, para ser exato) pode ser representada de forma exata pelo formato de ponto flutuante de JavaScript. Isso significa que, quando se está trabalhando com números reais em JavaScript, a representação do número frequentemente será uma aproximação dele. 34 Parte I JavaScript básica A representação em ponto flutuante IEEE-754 utilizada em JavaScript (e por praticamente todas as outras linguagens de programação modernas) é uma representação binária que pode descrever frações como 1/2, 1/8 e 1/1024 com exatidão. Infelizmente, as frações que usamos mais comumen- te (especialmente ao executarmos cálculos financeiros) são decimais: 1/10, 1/100, etc. As represen- tações em ponto flutuante binárias não conseguem representar números simples como 0.1 com exatidão. Os números em JavaScript têm muita precisão e podem se aproximar bastante de 0.1. Mas o fato de esse número não poder ser representado de forma exata pode causar problemas. Considere este código: var x =.3 –.2; // trinta centavos menos 20 centavos var y =.2 –.1; // vinte centavos menos 10 centavos x == y // => falso: os dois valores não são os mesmos! x ==.1 // => falso:.3-.2 não é igual a.1 y ==.1 // => verdadeiro:.2-.1 é igual a.1 Devido ao erro de arredondamento, a diferença entre as aproximações de.3 e.2 não é exatamente igual à diferença entre as aproximações de.2 e.1. É importante entender que esse problema não é específico da linguagem JavaScript: ele afeta qualquer linguagem de programação que utilize núme- ros binários em ponto flutuante. Além disso, note que os valores x e y no código anterior são muito próximos entre si e do valor correto. Os valores calculados são adequados para quase todas as finali- dades – o problema surge quando tentamos comparar a igualdade de valores. Uma futura versão de JavaScript poderá suportar um tipo numérico decimal que evite esses pro- blemas de arredondamento. Até então, talvez você queira efetuar cálculos financeiros importantes usando inteiros adaptados. Por exemplo, você poderia manipular valores monetários como centavos inteiros, em vez de frações de moeda. 3.1.5 Datas e horas JavaScript básico inclui uma construtora Date() para criar objetos que representam datas e horas. Esses objetos Date têm métodos que fornecem uma API para cálculos simples de data. Os objetos Date não são um tipo fundamental como os números. Esta seção apresenta um estudo rápido sobre o trabalho com datas. Detalhes completos podem ser encontrados na seção de referência: var then = new Date(2010, 0, 1); // O 1º dia do 1º mês de 2010 var later = new Date(2010, 0, 1, // O mesmo dia, às 5:10:30 da tarde, hora local 17, 10, 30); var now = new Date(); // A data e hora atuais var elapsed = now – then; // Subtração de data: intervalo em milissegundos later.getFullYear() // => 2010 later.getMonth() // => 0: meses com base em zero later.getDate() // => 1: dias com base em um later.getDay() // => 5: dia da semana. 0 é domingo, 5 é sexta-feira. later.getHours() // => 17: 5 da tarde, hora local later.getUTCHours() // Horas em UTC; depende do fuso horário Capítulo 3 Tipos, valores e variáveis 35 later.toString() // => "Sexta-feira, 01 de janeiro de 2010, 17:10:30 GMT-0800 JavaScript básica // (PST)" later.toUTCString() // => "Sábado, 02 de janeiro de 2010, 01:10:30 GMT" later.toLocaleDateString() // => "01/01/2010" later.toLocaleTimeString() // => "05:10:30 PM" later.toISOString() // => "2010-01-02T01:10:30.000Z"; somente ES5 3.2 Texto Uma string é uma sequência ordenada imutável de valores de 16 bits, cada um dos quais normal- mente representa um caractere Unicode – as strings são um tipo de JavaScript usado para representar texto. O comprimento de uma string é o número de valores de 16 bits que ela contém. As strings (e seus arrays) de JavaScript utilizam indexação com base em zero: o primeiro valor de 16 bits está na posição 0, o segundo na posição 1 e assim por diante. A string vazia é a string de comprimento 0. JavaScript não tem um tipo especial que represente um único elemento de uma string. Para repre- sentar um único valor de 16 bits, basta usar uma string que tenha comprimento 1. Caracteres, posições de código e strings em JavaScript JavaScript usa a codificação UTF-16 do conjunto de caracteres Unicode e as strings em JavaScript são sequências de valores de 16 bits sem sinal. Os caracteres Unicode mais comumente usados (os do “plano básico multilíngue") têm posições de código que cabem em 16 bits e podem ser representados por um único elemento de uma string. Os caracteres Unicode cujas posições de código não cabem em 16 bits são codificados de acordo com as regras da UTF-16 como uma sequência (conhecida como “par substituto”) de dois valores de 16 bits. Isso significa que uma string JavaScript de comprimento 2 (dois valores de 16 bits) pode representar apenas um caractere Unicode: var p = "π"; // π é 1 caractere com posição de código de 16 bits 0x03c0 var e = "e"; // e é 1 caractere com posição de código de 17 bits 0x1d452 p.length // => 1: p consiste em 1 elemento de 16 bits e.length // => 2: a codificação UTF-16 de e são 2 valores de 16 bits: "\ud835\ // udc52" Os diversos métodos de manipulação de strings definidos em JavaScript operam sobre valores de 16 bits e não sobre caracteres. Eles não tratam pares substitutos de forma especial, não fazem a normalização da string e nem mesmo garantem que uma string seja UTF-16 bem formada. 3.2.1 Strings literais Para incluir uma string literalmente em um programa JavaScript, basta colocar os caracteres da string dentro de um par combinado de aspas simples ou duplas (' ou "). Os caracteres de aspas duplas podem estar contidos dentro de strings delimitadas por caracteres de aspas simples e estes podem estar contidos dentro de strings delimitadas por aspas duplas. Aqui estão exemplos de strings literais: "" // A string vazia: ela tem zero caracteres 'testing' "3.14" 36 Parte I JavaScript básica 'name="myform"' "Wouldn't you prefer O'Reilly's book?" "This string\nhas two lines" "π is the ratio of a circle's circumference to its diameter" Em ECMAScript 3, as strings literais devem ser escritas em uma única linha. Em ECMAScript 5, no entanto, pode-se dividir uma string literal em várias linhas, finalizando cada uma delas, menos a última, com uma barra invertida (\). Nem a barra invertida nem a terminação de linha que vem depois dela fazem parte da string literal. Se precisar incluir um caractere de nova linha em uma string literal, use a sequência de caracteres \n (documentada a seguir): "two\nlines" // Uma string representando 2 linhas escritas em uma linha "one\ // Uma string de uma linha escrita em 3 linhas. Somente ECMAScript 5. long\ line" Note que, ao usar aspas simples para delimitar suas strings, você deve tomar cuidado com as contra- ções e os possessivos do idioma inglês, como can’t e O’Reilly’s. Como o apóstrofo é igual ao caractere de aspas simples, deve-se usar o caractere de barra invertida (\) para fazer o “escape” de qualquer apóstrofo que apareça em strings com aspas simples (os escapes estão explicados na próxima seção). Na programação JavaScript do lado do cliente, o código JavaScript pode conter strings de códi- go HTML e o código HTML pode conter strings de código JavaScript. Assim como JavaScript, HTML utiliza aspas simples ou duplas para delimitar suas strings. Assim, ao se combinar JavaScript e HTML, é uma boa ideia usar um estilo de aspas para JavaScript e outro para HTML. No exemplo a seguir, a string “Thank you” está entre aspas simples dentro de uma expressão JavaScript, a qual é colocada entre aspas duplas dentro de um atributo de rotina de tratamento de evento em HTML: Click Me 3.2.2 Sequências de escape em strings literais O caractere de barra invertida (\) tem um propósito especial nas strings em JavaScript. Combinado com o caractere que vem a seguir, ele representa um caractere que não pode ser representado de outra forma dentro da string. Por exemplo, \n é uma sequência de escape que representa um caractere de nova linha. Outro exemplo, mencionado anteriormente, é o escape \’, que representa o caractere de aspas sim- ples (ou apóstrofo). Essa sequência de escape é útil quando se precisa incluir um apóstrofo em uma string literal que está contida dentro de aspas simples. Você pode ver por que elas são chamadas de sequências de escape: a barra invertida permite escapar da interpretação normal do caractere de aspas simples. Em vez de utilizá-lo para marcar o final da string, você o utiliza como um apóstrofo: 'You\'re right, it can\'t be a quote' A Tabela 3-1 lista as sequências de escape em JavaScript e os caracteres que representam. Duas se- quências de escape são genéricas e podem ser usadas para representar qualquer caractere, especifican- do-se seu código de caractere Latin-1 ou Unicode como um número hexadecimal. Por exemplo, a sequência \xA9 representa o símbolo de direitos autorais, o qual tem a codificação Latin-1 dada pelo número hexadecimal A9. Da mesma forma, o escape \u representa um caractere Unicode arbitrário especificado por quatro dígitos hexadecimais; \u03c0 representa o caractere π, por exemplo. Capítulo 3 Tipos, valores e variáveis 37 Tabela 3-1 Sequências de escape em JavaScript JavaScript básica Sequência Caractere representado \0 O caractere NUL (\u0000) \b Retrocesso (\u0008) \t Tabulação horizontal (\u0009) \n Nova linha (\u000A) \v Tabulação vertical (\u000B) \f Avanço de página (\u000C) \r Retorno de carro (\u000D) \" Aspas duplas (\u0022) \' Apóstrofo ou aspas simples (\u0027) \\ Barra invertida (\u005C) \x XX O caractere Latin-1 especificado pelos dois dígitos hexadecimais XX \u XXXX O caractere Unicode especificado pelos quatro dígitos hexadecimais XXXX Se o caractere \ precede qualquer outro caractere que não seja um dos mostrados na Tabela 3-1, a barra invertida é simplesmente ignorada (embora, é claro, versões futuras da linguagem possam definir novas sequências de escape). Por exemplo, \# é o mesmo que #. Por fim, conforme observado anteriormente, a ECMAScript 5 permite que uma barra invertida antes de uma quebra de linha divida uma string literal em várias linhas. 3.2.3 Trabalhando com strings Um dos recursos incorporados a JavaScript é a capacidade de concatenar strings. Se o operador + é utilizado com números, ele os soma. Mas se esse operador é usado em strings, ele as une, anexando a segunda na primeira. Por exemplo: msg = "Hello, " + "world"; // Produz a string "Hello, world" greeting = "Welcome to my blog," + " " + name; Para determinar o comprimento de uma string – o número de valores de 16 bits que ela contém – use sua propriedade length. Determine o comprimento de uma string s como segue: s.length Além dessa propriedade length, existem vários métodos que podem ser chamados em strings (como sempre, consulte a seção de referência para ver detalhes completos): var s = "hello, world" // Começa com um texto. s.charAt(0) // => "h": o primeiro caractere. s.charAt(s.length-1) // => "d": o último caractere. s.substring(1,4) // => "ell": o 2º, 3º e 4º caracteres. s.slice(1,4) // => "ell": a mesma coisa s.slice(-3) // => "rld": os últimos 3 caracteres s.indexOf("l") // => 2: posição da primeira letra l. s.lastIndexOf("l") // => 10: posição da última letra l. s.indexOf("l", 3) // => 3: posição do primeiro "l" em ou após 3 38 Parte I JavaScript básica s.split(", ") // => ["hello", "world"] divide em substrings s.repla