Como desenvolver games para Smart TVs – Parte 02

Con­tin­uan­do nos­so mini cur­so hoje vamos com­preen­der que as Smart TVs são divi­di­das em 3 prin­ci­pais gru­pos quan­do o assun­to é desen­volvi­men­to de games ou apps.

Logo abaixo dividi­mos os em 3 prin­ci­pais gru­pos com seus respec­tivos fab­ri­cantes, sis­temas opera­cionais e tec­nolo­gias uti­lizadas:

1 — Sam­sung — TIZEN (Html, Css e JavaScript)

2 — LG — WebOS (Html, Css e JavaScript)

3 — SONY — Android TV — (Java Android)

A princí­pio vamos nos con­cen­trar nos dois primeiros gru­pos em nos­so cur­so. Observem um detal­he, tan­to a Sam­sung como a LG apre­sen­tam em comum as mes­mas tec­nolo­gias para desen­volvi­men­to, entre­tan­to há difer­enças na práti­ca, ou seja, suas imple­men­tações são bem dis­tin­tas.

O ide­al seria que o aluno já ten­ha algum con­hec­i­men­to em HTML, CSS e JavaScript ou jQUERY, mas vamos faz­er uma breve intro­dução das 3 tec­nolo­gias a seguir:

HTML

HTML é uma das lin­gua­gens que uti­lizamos para desen­volver web­sites. O acrôn­i­mo HTML vem do inglês e sig­nifi­ca Hyper­text Markup Lan­guage ou em por­tuguês Lin­guagem de Mar­cação de Hiper­tex­to.

O HTML é a liguagem base da inter­net. Foi cri­a­da para ser de fácil entendi­men­to por seres humanos e tam­bém por máquinas, como por exem­p­lo o Google ou out­ros sis­temas que per­cor­rem a inter­net cap­turan­do infor­mação.

Quem criou o HTML?

Tim Bern­ers-Lee. Esse é o nome do homem que criou o HTML. Ele criou o HTML para a comu­ni­cação e dis­sem­i­nação de pesquisas entre ele e seu grupo de cole­gas. O HTML ficou bas­tante con­heci­do quan­do começou a ser uti­liza­da para for­mar a rede públi­ca daque­la época, o que se tornar­ia mais tarde a inter­net que con­hece­mos hoje.

O que são as tags do HTML?

O HTML é uma lin­guagem basea­da em mar­cação. Nós mar­camos os ele­men­tos para mostrar quais infor­mações a pági­na exibe. Por exem­p­lo, um títu­lo impor­tante. Aque­le títu­lo do arti­go, da manchete do site, nós mar­camos com uma tag/elemento chama­do H1. Veja um exem­p­lo:

<h1>Aqui vai o texto do título</h1>

Perce­ba que o tex­to está entre duas mar­cações. Essas mar­cações são chamadas de TAGS. As tags são aber­tas e depois fechadas. No exem­p­lo aci­ma abri­mos a tag com

e fechamos com

. O que está den­tro é o con­teú­do mostra­do para o usuário.

O pará­grafos são mar­ca­dos com a tag P. Assim:

<p>Aqui vai o texto do parágrafo. 
Geralmente parágrafos tem muitas palavras, 
letras menores que as do título</p>

Uti­lizan­do as tags, nós dize­mos para o nave­g­ador o que é cada infor­mação. O que é um títu­lo, o que é um pará­grafo, o que é um botão, um for­mulário etc. Dize­mos tam­bém o que é cada coisa para os sis­temas de bus­ca, como o Google. O Google, nesse caso, para exibir os resul­ta­dos de bus­ca, ele pre­cisa saber o que é um pará­grafo e o que é um títu­lo. Ele sabe dis­so através das tags.

A estrutura básica

Todo HTML começa do mes­mo jeito. Não há seg­re­dos aqui. Você pode sim­ples­mente copi­ar em algum lugar para usar esse códi­go toda vez ini­ciar um novo HTML.

<!DOCTYPE html>

<html lang="pt-br">
<head>
    <meta charset="utf-8">
    <title>Título da página</title>
</head>
<body>
 ... aqui vai todo o codigo HTML que faz seu site...
</body>
</html>

A primeira lin­ha se chama­da DOCTYPE. O Doc­type avisa aos browsers, robôs de bus­ca, leitores de tela e out­ras coisas que tipo de doc­u­men­to e aque­le que eles estao prestes a car­regar. Exis­tem out­ros códi­gos que podemos car­regar, por exem­p­lo XML. Por isso o Doc­type avisa o brows­er para que ele sai­ba como se com­por­tar ao ler o códi­go.

Depois começamos com a Tag HTML. Isso quer diz­er que todo o que estiv­er entre as tags é escrito em HTML. Ao lado da palavra HTML tem um atrib­u­to (expli­co o que são atrib­u­tos mais pra frente) chama­do lang, onde indicamos qual o idioma do tex­to que escrever­e­mos.

Logo após a tag html temos a tag . Na tag Head nós indicamos o títu­lo do doc­u­men­to e indicamos a tabela de car­ac­téres que o brows­er deve usar para ren­derizar seu tex­to. Tam­bém não se pre­ocupe com isso ago­ra.

A tag <tit­tle> é muito impor­tante. É com ela que você indi­ca o títu­lo do doc­u­men­to. O Google e out­ros sis­temas de bus­ca uti­lizam essa tag para indicar em suas bus­cas o títu­lo da págin. Isso é muito impor­tante para que você apareça bem nas bus­cas.

Logo depois da tag de fechamen­to começamos a tag . Den­tro deste ele­men­to é que vamos escr­ev­er todo o códi­go HTML do resto do site.

<!DOCTYPE html>

<html lang="pt-br">
<head>
    <meta charset="utf-8">
    <title>Título da página</title>
</head>
<body>
   <h1>Aqui vai o texto do título</h1>
   <p>Aqui vai o texto do parágrafo. 
   Geralmente parágrafos tem muitas palavras, letras menores que as do título</p>
</body>
</html>

Criando seu primeiro HTML

Para cri­ar seu HTML é muito sim­ples. Primeiro, abra e crie um arqui­vo vazio, sem tex­to, com o nome index.html. Uti­lize o Notepad (se estiv­er no win­dows) ou o TextE­d­it (se estiv­er no Mac).

Perce­ba que a exten­são do seu arqui­vo é .html e não .txt

Feito isso, copie o códi­go uti­liza­do no exem­p­lo aci­ma e cole neste doc­u­men­to. Salve e abra no seu nave­g­ador. Voilá! Você fez seu primeiro arqui­vo HTML

Um pouco avançado: Desenvolvimento em Camadas

Um dos prin­ci­pais prob­le­mas no desen­volvi­men­to para inter­net é a mis­tu­ra dos diver­sos códi­gos. Nós não usamos ape­nas o HTML para faz­er sites. Além do HTML, uti­lizamos ain­da o CSS, que é uma lin­guagem para con­fig­u­rar­mos o visu­al das pági­nas e o Javascript, que vai cuidar do com­por­ta­men­to da pági­na, por exem­p­lo, o que acon­tece quan­do o usuário cli­ca em um botão.

Há tam­bém as lin­gua­gens chamadas Lin­gua­gens Serv­er-Side, que são lin­gua­gens como PHP, Python, Ruby, ASP e etc. Essas lin­gua­gens fazem tudo fun­cionar. Elas fazem os cál­cu­los nos servi­dores e dão a respos­ta para o nave­g­ador do usuário.

Para que os códi­gos não se mis­turem, nós os sep­a­ramos em diver­sas camadas. Para ficar mais fácil de enten­der, imag­ine que o HTML é sem­pre o esquele­to do site. É com ele que vamos faz­er toda a estru­tu­ra de códi­go, onde ire­mos diz­er o que é um títu­lo, o que é um pará­grafo, uma imagem e etc. 

O CSS será a parte exter­na do cor­po. É o que deixará o esquele­to boni­to. É com o CSS que ire­mos dar cor para o títu­lo, con­fig­u­rar o taman­ho do tex­to, largu­ra das col­u­nas e etc.

Dessa for­ma nós não mis­tu­ramos o códi­go HTML e o códi­go CSS. Uti­lizamos a mes­ma ideia para sep­a­rar os out­ros códi­gos cita­dos aci­ma.

O que é CSS?

CSS é chama­do de lin­guagem Cas­cad­ing Style Sheet e é usa­do para estilizar ele­men­tos escritos em uma lin­guagem de mar­cação como HTML. O CSS sep­a­ra o con­teú­do da rep­re­sen­tação visu­al do site. Pense  na dec­o­ração da sua pági­na. Uti­lizan­do o CSS é pos­sív­el alter­ar a cor do tex­to e do fun­do, fonte e espaça­men­to entre pará­grafos. Tam­bém pode cri­ar tabelas, usar vari­ações de lay­outs, ajus­tar ima­gens para suas respec­ti­vas telas e assim por diante.

CSS foi desen­volvi­do pelo W3C (World Wide Web Con­sor­tium) em 1996, por uma razão bem sim­ples. O HTML não foi pro­je­ta­do para ter tags que aju­dari­am a for­matar a pági­na. Você dev­e­ria ape­nas escr­ev­er a mar­cação para o site.

Tags como <font> foram intro­duzi­das na ver­são 3.2 do HTML e causaram muitos prob­le­mas para os desen­volve­dores. Como os sites tin­ham difer­entes fontes, cores e esti­los, era um proces­so lon­go, doloroso e caro para ree­scr­ev­er o códi­go. Assim, o CSS foi cri­a­do pelo W3C para resolver este prob­le­ma.

A relação entre HTML e CSS é bem forte. Como o HTML é uma lin­guagem de mar­cação (o alicerce de um site) e o CSS é foca­do no esti­lo (toda a estéti­ca de um site), eles andam jun­tos.

CSS não é tec­ni­ca­mente uma neces­si­dade, mas provavel­mente você não gostaria de olhar para um site que usa ape­nas HTML, pois isso pare­ce­ria com­ple­ta­mente aban­don­a­do.

Vantagens do CSS

A difer­ença entre um site que imple­men­ta CSS e out­ro que não o usa é gigan­tesca e notáv­el.

Você já deve ter vis­to um site que não car­rega com­ple­ta­mente ou tem um plano de fun­do bran­co com tex­to azul e pre­to. Isso sig­nifi­ca que a parte CSS do site não foi car­rega­da cor­re­ta­mente ou não existe.

E é assim que um site somente com HTML se parece. Acred­i­to que você vai con­cor­dar comi­go de que isso não é muito boni­to, cer­to?

Antes de usar CSS, toda a estiliza­ção tin­ha que ser incluí­da na mar­cação HTML. Isso sig­nifi­ca que você dev­e­ria descr­ev­er sep­a­rada­mente todo o plano de fun­do, as cores das fontes, os alin­hamen­tos, etc.

Mas o CSS per­mite que você estilize tudo em um arqui­vo difer­ente, crian­do assim o esti­lo sep­a­rada­mente. E, mais tarde, faça inte­gração do arqui­vo CSS na parte supe­ri­or da mar­cação HTML. Isso man­tém a mar­cação HTML limpa e fácil de man­ter.

Resu­min­do, com o CSS você não pre­cisa mais escr­ev­er repeti­da­mente como os ele­men­tos indi­vid­u­ais se pare­cem. Isso econ­o­miza tem­po, encur­ta o códi­go e diminui a chance de erros.

O CSS per­mite que você ten­ha vários esti­los em uma pági­na HTML, tor­nan­do as pos­si­bil­i­dades de per­son­al­iza­ção quase infini­tas. Hoje em dia, isso está se tor­nan­do mais uma neces­si­dade do que um sim­ples recur­so.

Como CSS Funciona

O CSS é uma fer­ra­men­ta muito potente que pos­si­bili­ta cri­ar diver­sas fun­cional­i­dades ao invés de usar JavaScript ou out­ra lin­guagem mais pesa­da. Se usa­do com mod­er­ação, CSS pode via­bi­lizar uma óti­ma exper­iên­cia ao desen­volve­dor e usuários das pági­nas web.

Com o Cas­cad­ing Style Sheets é pos­sív­el cri­ar ani­mações com­plexas, cri­ar efeitos com uso de par­al­lax, que faz pare­cer que a imagem de fun­do tem uma pro­fun­di­dade difer­ente um dos out­ros, cri­ar sites inter­a­tivos e tam­bém jogos com HTML5 e CSS3.

O CSS usa uma sin­taxe sim­ples basea­da em inglês com um con­jun­to de regras que o gov­er­nam. Como men­cionamos ante­ri­or­mente, o HTML nun­ca teve a intenção de usar ele­men­tos de esti­lo, ape­nas a mar­cação da pági­na. Foi cri­a­do para descr­ev­er ape­nas o con­teú­do. Por exem­p­lo: <p>Este é um parágrafo.</p>.

Mas como você estiliza o pará­grafo? A estru­tu­ra da sin­taxe CSS é bem sim­ples. Tem um sele­tor e um blo­co de declar­ação. Você sele­ciona um ele­men­to e depois declara o que dese­ja faz­er com ele. Bas­tante sim­ples, cer­to?

Mas tem algu­mas regras que você pre­cisa saber. Isso tam­bém é sim­ples, não se pre­ocupe.

O sele­tor apon­ta para o ele­men­to HTML que você dese­ja estilizar. O blo­co de declar­ação con­tém uma ou mais declar­ações sep­a­radas por pon­to e vír­gu­la.

Cada declar­ação inclui um nome de pro­priedade CSS e um val­or, sep­a­ra­dos por dois pon­tos. Uma declar­ação CSS sem­pre ter­mi­na com um pon­to-e-vír­gu­la e os blo­cos de declar­ação são cer­ca­dos por chaves.

Vamos ver um exem­p­lo:

Todos os ele­men­tos <p> serão estiliza­dos e serão col­ori­dos de azul e negri­to.

  1. <style>
  2. p {
  3. col­or: blue;
  4. text-weight: bold;
  5. }
  6. <style>

Em out­ro exem­p­lo, todos os ele­men­tos <p> serão cen­tral­iza­dos, com taman­ho 16x e de cor pink.

  1. <style>
  2. p {
  3. text-align: cen­ter;
  4. font-size: 16px;
  5. col­or: pink;
  6. }
  7. </style>

Anatomia de um comando CSS

O CSS estip­u­la regras para o arqui­vo em html. Com cada regra é pos­sív­el estilizar o con­teú­do todo ou somente deter­mi­na­dos ele­men­tos. Por isso enten­da, um coman­do bási­co é com­pos­to por sele­tor e declar­ações, que con­tém pro­priedade e val­or.

SELETOR {PROPRIEDADE: VALOR}

A sin­taxe do CSS é muito sim­ples de apren­der. O sele­tor sele­ciona quais ele­men­tos em html rece­berão a pro­priedade. Pode ser p (pará­grafo) ou o body (cor­po da sua pági­na). Já a pro­priedade pode ser a cor ou algo mais especí­fi­co como cor do fun­do (back­ground). E por últi­mo o val­or, que deter­mi­na o val­or da pro­priedade.

Vamos sim­u­lar um exem­p­lo. Dig­amos que o obje­ti­vo é mudar a fonte de uma tag h1. Para isso podemos usar h1 {font-size: 20px;}

  • h1 – é o sele­tor. Neste caso sele­cionamos o h1.
  • font-size – é a declar­ação que con­tém  a pro­priedade (font-size) e o val­or é (20px).

Lista de comandos básicos CSS

São tan­tas opções entre sele­tores, pro­priedades e val­ores que pode ser muito difí­cil para um desen­volve­dor lem­brar de todos eles ape­nas con­fian­do na memória. Por isso decidi­mos cri­ar uma Lista de Coman­dos Bási­cos CSS (CSS3 Inclu­so) que servirá de aju­da para você que está apren­den­do sobre o que é CSS.

 Este doc­u­men­to foi estrate­gi­ca­mente estru­tu­ra­do e divi­di­do em seções para facil­i­tar sua leitu­ra. Faça down­load da Lista de Coman­dos CSS em PDF cli­can­do aqui e apro­funde seus con­hec­i­men­tos sobre o que é CSS.

Estilos CSS Interno, Externo e Inline

Anal­is­are­mos cada esti­lo de for­ma ráp­i­da! Para uma expli­cação detal­ha­da, acesse o link que vamos disponi­bi­lizar logo abaixo.

Vamos começar com o esti­lo inter­no. Esti­los CSS feitos des­ta for­ma são car­rega­dos cada vez que um site é atu­al­iza­do, o que pode aumen­tar o tem­po de car­rega­men­to. Além dis­so, você não poderá usar o mes­mo esti­lo CSS em várias pági­nas, pois está con­ti­do em uma úni­ca pági­na. Mas a van­tagem dis­so é que ter tudo em uma pági­na facili­ta o com­par­til­hamen­to do mod­e­lo para uma visu­al­iza­ção.

O méto­do exter­no pode ser o mais con­ve­niente. Tudo é feito exter­na­mente em um arqui­vo .css. Isso sig­nifi­ca que você pode faz­er todo o esti­lo em um arqui­vo sep­a­ra­do e aplicar o CSS a qual­quer pági­na dese­ja­da. O esti­lo exter­no tam­bém pode mel­ho­rar o tem­po de car­rega­men­to.

Por fim, tem tam­bém o esti­lo Inline do CSS. Inline tra­bal­ha com ele­men­tos especí­fi­cos que pos­suem a tag <style>. Cada com­po­nente deve ser estiliza­do, por isso talvez não seja o mel­hor ou o mais rápi­do para lidar com CSS. Mas pode ser útil, por exem­p­lo, para alter­ar um úni­co ele­men­to, visu­alizar rap­i­da­mente as alter­ações ou se não tiv­er aces­so aos arquiv­os CSS.

Como Criar uma Folha de Estilo

Para cri­ar uma fol­ha de esti­los é bem sim­ples. Bas­ta abrir seu edi­tor de códi­gos, como o Sub­lime, e cri­ar um doc­u­men­to novo.

Depois de cri­a­do, salve como estilo.css, mes­mo sem ain­da ter escrito nada (este .css é o que define um arqui­vo ser recon­heci­do pelo nave­g­ador como a fol­ha de esti­lo).

Como criar um folha de estilo CSS

Assim que for sal­vo, o edi­tor de tex­to vai con­seguir ler o arqui­vo com mais facil­i­dade, até mes­mo com sug­estões de auto com­plete enquan­to digi­ta os códi­gos da fol­ha de esti­lo, como mostra o print abaixo:

Como integrar o CSS no HTML?

Após sal­var como estilo.css pre­cisamos colo­car o arqui­vo em nos­so arqui­vo HTML, porque é ele quem vai car­regar o CSS, o CSS soz­in­ho não faz site! E é com tags de refer­ên­cia que você avisa ao HTML que existe um arqui­vo de esti­lo para ele, veja:

<link rel=”stylesheet” type=”text/css” href=”estilo.css”>

Esta tag vai indicar ao HTML que tem um arqui­vo CSS para ser adi­ciona­do à  pági­na. Isto deve ser adi­ciona­do den­tro da tag <head> </head> do seu HTML, como pode ver nesse print abaixo.

Como incorporar CSS no Html

Ago­ra abra o doc­u­men­to esti­lo .css com o Sub­lime, que provavel­mente está na mes­ma pas­ta do nos­so HTML.

Incorporando CSS no HTML

A par­tir des­ta últi­ma imagem, vamos enten­der como o CSS fun­ciona com três parâmet­ros bási­cos:

Elementos Básicos do CSS

Os ele­men­tos são tags do HTML, #id e .classe.

1. Tags HTML

  1. body
  2. h1
  3. h2
  4. h3
  5. h4
  6. h5
  7. h6
  8. span
  9. p

2. Classes CSS

Cri­ar e usar uma classe CSS é sim­ples. No doc­u­men­to CSS bas­ta colo­car .nome-da-classe-que-dese­ja . Abaixo cri­amos a classe títu­lo:

Criando classes no CSS

Note que existe um pon­to (.) antes do nome da classe. Isso faz com que o CSS enten­da que se está crian­do uma classe para ser usa­da no HTML.

Para se adi­cionar essa classe que cri­amos den­tro do CSS, bas­ta que na tag HTML ten­ha o parâmetro class=””.

Obser­vação: den­tro das aspas, não pre­cisa usar o pon­to (.) antes da classe pois o nome class no HTML já avisa para o CSS que é para ele bus­car pelo nome da classe com “.”

Criando classe título no CSS

Lem­bran­do que uma tag HTML, como h1 ou qual­quer out­ra, pode ter mais de uma classe, bas­ta sep­a­rá-las com espaço como mostra no exem­p­lo abaixo:

<h1 class=”titulo fonte-grande sublinhado”>Melhor site</h1>

Nes­ta tag foram usadas três class­es: “tit­u­lo”, “fonte-grande” e “sub­lin­hado”.

Mas para que todas estas class­es ten­ham efeito épre­ciso criá-las no CSS. Veja como cri­amos estas class­es:

Criando diversas classes no html
Exemplo de uso de CSS

Quan­do abrir­mos nos­so HTML o títu­lo dev­erá ficar assim:

3- Criando ID’s CSS:

O uso dos ID’s em CSS é pare­ci­do com as class­es, mas as prin­ci­pais difer­enças são que os id’s são iden­ti­fi­ca­dos com # e só podem ser usa­dos um id por tag html. Para adi­cionar um ID ao HTML, adi­cione como parâmetro id=””.

Veja que a quan­do usamos no HTML, tam­bém excluí­mos o #  do id da mes­ma for­ma que excluí­mos o . da classe.

Criando ID no CSS

Dessa for­ma, o botão dev­erá ficar assim:

criando botão com CSS

DICA: Este parâmetro de ID’s não é o mais apro­pri­a­do para se usar em uma pági­na para muitos botões pois pode causar con­fli­tos com a lin­guagem de pro­gra­mação JavaScript, que uti­liza nor­mal­mente dos ID’s no HTML para realizar ações mais com­plexas.

Como adicionar CSS no HTML sem a tag <link>?

Exis­tem duas out­ras maneiras de se adi­cionar CSS no HTML, ape­sar de não serem recomen­dadas dev­i­do a um padrão ado­ta­do mundial­mente, é nos­so dev­er te mostrar como faz.

1- Adicionar CSS no HTML sem uso do arquivo externo

Você pode adi­cionar o CSS colo­can­do o esti­lo den­tro do próprio HTML, sem usar um arqui­vo CSS exter­no como mostra o exem­p­lo abaixo:

Como adicionar CSS no HTML sem a tag link

Neste exem­p­lo, o esti­lo fica den­tro do HTML mes­mo com o uso da tag <style> den­tro da tag <head>. Isso faz com que tudo fique cen­tral­iza­do em um úni­co doc­u­men­to.

E por que não é recomen­da­do? Quan­do há muitas lin­has de esti­lo isso pode causar uma demo­ra ao abrir a pági­na uma vez que o nave­g­ador lê o seu doc­u­men­to de cima para baixo, lin­ha por lin­ha. Então se tiv­er muitas lin­has de esti­lo para ler, vai demor­ar mais para o con­teú­do da pági­na ser mostra­do.

Por isso, o ide­al é usar a tag <link> para que, ao invés de ler muitas lin­has de esti­lo, o nave­g­ador leia somente uma refer­ên­cia para out­ro arqui­vo e assim faz­er com que seu con­teú­do seja car­rega­do mais rap­i­da­mente.

2- Adicionar CSS no HTML utilizando o parâmetro style

Você pode adi­cionar CSS no HTML uti­lizan­do o parâmetro style em uma tag html especí­fi­ca. Mas isso afe­tará somente aque­la tag e não todas as demais tags com o mes­mo nome. Então, ao invés de usar­mos os parâmet­ros id=”” ou class=””, uti­lizare­mos o parâmetro style=””:

<h1 style=”font-size: 3rem;color: #333;text-align: cen­ter;”>

Veja como fica:

Adicionando css no html com parâmetro Style

E por que não é recomen­da­do? Este tipo de uso de esti­los se tor­na um prob­le­ma caso out­ros ele­men­tos ten­ham as mes­mas car­ac­terís­ti­cas do seu títu­lo, por exem­p­lo. Com isso, você teria que copi­ar todo o parâmetro style da tag h1.

Diante de dis­so, con­cluí­mos tam­bém que o mais recomen­da­do é o uso de class­es através de um arqui­vo de esti­lo exter­no ao CSS. Assim, con­seguimos usar os esti­los de for­ma mais limpa e ráp­i­da e é pos­sív­el reuti­lizar essas class­es em out­ras tags sem­pre que dese­jar, sem afe­tar o tem­po de car­rega­men­to da pági­na.

CSS3

Ape­sar de lança­da em 2010, CSS3 é a últi­ma ver­são da Fol­ha de Esti­lo em Cas­ca­ta e veio para acres­cen­tar de for­ma mel­ho­ra­da das ver­sões ante­ri­ores.

A mel­hor novi­dade é em relação a flex­i­bil­i­dade na cri­ação de lay­outs, trazen­do mais autono­mia para os web­de­sign­ers e tam­bém desen­volve­dores, que de cer­ta for­ma estão lig­a­dos ao visu­al do site.

Com o CSS3, é pos­sív­el elab­o­rar can­tos arredonda­dos, som­bras, efeitos gra­di­entes, ani­mações e efeitos de tran­sição, den­tre out­ras opções.

Alguns exem­p­los:

@keyframes exemplo {
    0% {background-color: red;}/*a animação começa vermelho*/
    50% {background-color: yellow;}/*a animação chega na metade em amarela*/
  100% {background-color: red;}/*a animação termina vermelha novamente*/

}
div {
    width: 100px;/*largura do elemento*/
    height: 100px;/*altura do elemento*/
    background-color: red;/*cor do inicial do elemento*/
    animation-name: exemplo;/*aqui vem o nome da animação*/
    animation-duration: 4s;/*tempo da duração do inicio ao fim*/
  animation-iteration-count:infinite;
}

E no html bas­ta colo­car a tag <div></div> e a ani­mação começará assim que o esti­lo con­teú­do do site for car­rega­do.

O que é JavaScript?

JavaScript é uma lin­guagem de script ori­en­ta­da a obje­tos, mul­ti­platafor­ma. É uma lin­guagem peque­na e leve. Den­tro de um ambi­ente de host (por exem­p­lo, um nave­g­ador web) o JavaScript pode ser lig­a­do aos obje­tos deste ambi­ente para prover um con­t­role pro­gramáti­co sobre eles.

JavaScript  tem uma bib­liote­ca padrão de obje­tos, como: ArrayDate, e Math, e um con­jun­to de ele­men­tos que for­mam o núcleo da lin­guagem, tais como: oper­adores, estru­turas de con­t­role e declar­ações. O núcleo do JavaScript pode ser esten­di­do para uma var­iedade de propósi­tos, com­ple­men­tan­do assim a lin­guagem:

  • O lado cliente do JavaScript estende-se do núcleo lin­guagem, fornecen­do obje­tos para con­tro­lar um nave­g­ador web e seu Doc­u­ment Object Mod­el (DOM). Por exem­p­lo, as exten­sões do lado do cliente per­mitem que uma apli­cação coloque ele­men­tos em um for­mulário HTML e respon­da a even­tos do usuário, como cliques do mouse, entra­da de for­mulário e de nave­g­ação da pági­na.
  • O lado do servi­dor do JavaScript estende-se do núcleo  da lin­guagem, fornecen­do obje­tos rel­e­vantes à exe­cução do JavaScript em um servi­dor. Por exem­p­lo, as exten­sões do lado do servi­dor per­mitem que uma apli­cação comu­nique-se com um ban­co de dados, garan­ti­n­do a con­tinuidade de infor­mações de uma chama­da para a out­ra da apli­cação, ou exe­cu­tar manip­u­lações de arquiv­os em um servi­dor.

JavaScript não é Java

JavaScript e Java são sim­i­lares em algu­mas coisas, mas são difer­entes em out­ras. O JavaScript assemel­ha-se ao Java, porém não pos­sui tipagem estáti­ca e checagem rigí­da de tipos como o Java. JavaScript segue a sin­taxe bási­ca do Java, con­venções de nomen­clatu­ra e con­struções de con­t­role de fluxo, razões pelas quais esta lin­guagem foi renomea­da de Live­Script para JavaScript.

Em con­traste com o sis­tema em tem­po de com­pi­lação das class­es con­struí­das por declar­ações no Java, JavaScript supor­ta um sis­tema em tem­po de exe­cução com base em um pequeno número de tipos de dados rep­re­sen­tan­do val­ores numéri­cos, booleanos, e strings. JavaScript tem um mod­e­lo de obje­to basea­do em pro­tótipo em vez do mod­e­lo, mais comum, de obje­to basea­do em class­es. O mod­e­lo basea­do em pro­tótipo fornece her­ança dinâmi­ca; isto é, o que é her­da­do pode vari­ar para obje­tos indi­vid­u­ais. JavaScript tam­bém supor­ta funções sem quais­quer req­ui­si­tos espe­ci­ais declar­a­tivos. As funções podem ser pro­priedades de obje­tos, exe­cu­tan­do como méto­dos.

JavaScript é uma lin­guagem mais livre em com­para­ção a Java. Você não tem de declarar todas as var­iáveis, class­es e méto­dos. Você não tem que se pre­ocu­par com o fato dos méto­dos serem públi­cos, pri­va­dos ou pro­te­gi­dos, e você não tem que imple­men­tar inter­faces. Var­iáveis, parâmet­ros e tipo de retorno da função não são explici­ta­mente tipa­dos.

Java é uma lin­guagem de pro­gra­mação basea­da em class­es, pro­je­ta­da para exe­cução ráp­i­da e segu­rança de tipos. Segu­rança de tipo sig­nifi­ca que, por exem­p­lo, você não pode con­vert­er um número inteiro em Java para uma refer­ên­cia de obje­to ou aces­sar a memória pri­va­da cor­rompen­do byte­codes Java. O mod­e­lo basea­do em class­es do Java sig­nifi­ca que os pro­gra­mas são exclu­si­va­mente con­sti­tuí­dos por class­es e seus méto­dos. Her­ança de classe do Java e tipagem forte geral­mente requerem hier­ar­quias de obje­tos forte­mente acopla­dos. Ess­es req­ui­si­tos tor­nam a pro­gra­mação em Java mais com­plexa do que a pro­gra­mação em JavaScript.

Em con­traste,  JavaScript descende em espíri­to de uma lin­hagem de lin­gua­gens menores com tipagem dinâmi­ca, como Hyper­Talk e dBASE. Essas lin­gua­gens de script ofer­e­cem fer­ra­men­tas de pro­gra­mação para um públi­co muito mais amp­lo por causa de sua sin­taxe mais fácil, funções espe­cial­izadas embu­ti­das e req­ui­si­tos mín­i­mos para a cri­ação de obje­tos.

JavaScriptJava
Ori­en­ta­da a obje­to. Sem dis­tinção entre tipos e obje­tos. A her­ança é fei­ta através do pro­tótipo e as pro­priedades e méto­dos podem ser adi­cionadas a qual­quer obje­to dinami­ca­mente.Basea­da em class­es. Obje­tos são divi­di­dos em class­es e instân­cias com toda a her­ança através da hier­ar­quia da classe. Class­es e instân­cias não podem ter pro­priedades ou méto­dos adi­ciona­dos dinami­ca­mente.
Os tipos de dados das var­iáveis não pre­cisam ser declar­a­dos (tipagem dinâmi­ca)Os tipos de dados das var­iáveis devem ser declar­a­dos (tipagem estáti­ca).
Não pode escr­ev­er auto­mati­ca­mente no dis­co rigí­do.Pode escr­ev­er auto­mati­ca­mente no dis­co rigí­do.
Lin­guagem não com­pi­la­daLin­guagem com­pi­la­da

Começando com JavaScript

Começar a apren­der JavaScript é fácil: Tudo o que você pre­cisa é de um nave­g­ador web mod­er­no. Esse guia inclui algu­mas car­ac­terís­ti­cas do JavaScript que só estão disponíveis nas últi­mas ver­sões do Fire­fox, então, é recomendáv­el o uso de uma ver­são mais recente do Fire­fox.

Há duas fer­ra­men­tas no Fire­fox que são muito úteis para apren­der JavaScript: O con­sole web e o Scratch­pad.

O con­sole web mostra infor­mações sobre a pági­na web que está sendo car­rega­da atual­mente e tam­bém inclui a lin­ha de coman­do que você pode uti­lizar para exe­cu­tar códi­gos JavaScript na pági­na atu­al.

Para abrir o con­sole (Ctrl+Shift+K), sele­cione “Web Con­sole” do menu “Web Devel­op­er”, que está sob o menu “Tools” no Fire­fox. Ele aparece na parte infe­ri­or da janela do nave­g­ador. Na parte infe­ri­or do con­sole está a lin­ha de coman­do que você pode usar para colo­car o JavaScript, e a saí­da é exibi­da no painel aci­ma:

O Web Con­sole é exce­lente para exe­cu­tar lin­has úni­cas de JavaScript, mas emb­o­ra você pos­sa exe­cu­tar várias lin­has, não é muito con­ve­niente para isso, e você não pode sal­var as amostras de códi­go usan­do o Web Con­sole. Assim, para exem­p­los mais com­plex­os a fer­ra­men­ta Scratch­pad é mel­hor.

Para abrir o Scratch­pad (Shift+F4), sele­cione “Scratch­pad” do menu “Web Devel­op­er”, que está sob o menu “Tools/Ferramentas” do Fire­fox. Ele abre em uma janela sep­a­ra­da e é um edi­tor que você pode usar para escr­ev­er e exe­cu­tar JavaScript no nave­g­ador. Você tam­bém pode sal­var os scripts para o dis­co e car­regá-los a par­tir do dis­co.  

Para começar a escr­ev­er JavaScript, abra o Con­sole Web ou o Scratch­pad e escre­va seu primeiro códi­go JavaScript “Olá, mun­do”. 

function greetMe(nome) {
  alert("Olá, " + nome);
}

greetMe("mundo"); // "Olá, mundo"

Logo após, pres­sione Ctrl+R para exe­cu­tar o códi­go em seu nave­g­ador.

Nas pági­nas seguintes, este guia irá apre­sen­tar-lhe a sin­taxe e as car­ac­terís­ti­cas da lin­guagem JavaScript, de modo que você pos­sa escr­ev­er apli­cações mais com­plexas.

Sintaxe básica

JavaScript pega empresta­do a maior parte de sua sin­taxe do Java, mas tam­bém é influ­en­ci­a­do por Awk, Perl e Python.

JavaScript é case-sen­si­tive e usa o con­jun­to de car­ac­teres Uni­code. Por exem­p­lo, a palavra Früh (que sig­nifi­ca “cedo” em Alemão) pode ser usa­da como nome de var­iáv­el.

var Früh = "foobar";

Mas a var­iáv­el früh não é a mes­ma que Früh porque JavaScript é case sen­si­tive.

No JavaScript, instruções são chamadas de declar­ação e são sep­a­radas por um pon­to e vír­gu­la (;). Espaços, tab­u­lação e uma nova lin­ha são chama­dos de espaços em bran­co. O códi­go fonte dos scripts em JavaScript são lidos da esquer­da para a dire­i­ta e são con­ver­tidos em uma sequên­cia de ele­men­tos de entra­da como sim­bo­los, car­ac­teres de con­t­role, ter­mi­nadores de lin­ha, comen­tários ou espaço em bran­co. ECMAScript tam­bém define deter­mi­nadas palavras-chave e lit­erais, e tem regras para inserção automáti­ca de pon­to e vír­gu­la (ASI) para ter­mi­nar as declar­ações. No entan­to, recomen­da-se sem­pre adi­cionar pon­to e vír­gu­la no final de suas declar­ações; isso evi­tará alguns impre­vis­tos. Para obter mais infor­mações, con­sulte a refer­ên­cia detal­ha­da sobre a gramáti­ca léx­i­ca do JavaScript.

Comentários

A sin­taxe dos comen­tários em JavaScript é semel­hante como em C++ e em muitas out­ras lin­gua­gens:

// comentário de uma linha
 
/* isto é um comentário longo
   de múltiplas linhas.
 */
 
/* Você não pode, porém, /* aninhar comentários */ SyntaxError */

Declarações

Exis­tem três tipos de declar­ações em JavaScript.varDeclara uma var­iáv­el, opcional­mente, inicializando‑a com um val­or. letDeclara uma var­iáv­el local de escopo do blo­co, opcional­mente, inicializando‑a com um val­or. constDeclara uma con­stante de escopo de blo­co, ape­nas de leitu­ra.

Variáveis

Você usa var­iáveis como nomes sim­bóli­cos para os val­ores em sua apli­cação. O nome das var­iáveis, chama­dos de iden­ti­fi­cadores, obe­de­cem deter­mi­nadas regras.

Um iden­ti­fi­cador JavaScript deve começar com uma letra, under­line (_), ou cifrão ($); os car­ac­teres sub­se­quentes podem tam­bém ser números (0–9). Dev­i­do JavaScript ser case-sen­si­tive, letras incluem car­ac­teres de “A” a “Z” (maiús­cu­los) e car­ac­teres de “a” a “z” (minús­cu­los).

Você pode usar a ISO 8859–1 ou car­ac­teres Uni­code tal como os iden­ti­fi­cadores å e ü. Você pode tam­bém usar as sequên­cias de escape Uni­code como car­ac­teres e iden­ti­fi­cadores.

Alguns exem­p­los de nomes legais são Numeros_visitastemp99, e _nome.

Declarando variáveisS

Você pode declarar uma var­iáv­el de três for­mas:

  • Com a palavra chave var. Por exem­p­lo, var x = 42. Esta sin­taxe pode ser usa­da para declarar tan­to var­iáveis locais como var­iáveis globais.
  • Por sim­ples adição de val­or. Por exem­p­lo, x = 42. Isso declara uma var­iáv­el glob­al. Essa declar­ação gera um avi­so de advertên­cia no JavaScript. Você não deve usar essa vari­ante.
  • Com a palavra chave let. Por exem­p­lo, let y = 13. Essa sin­taxe pode ser usa­da para declarar uma var­iáv­el local de escopo de blo­co. Veja escopo de var­iáv­el abaixo.

Classificando variáveis

Uma var­iáv­el declar­a­da usan­do a declar­ação var ou let sem especi­ficar o val­or ini­cial tem o val­or  undefined.

Uma ten­ta­ti­va de aces­sar uma var­iáv­el não declar­a­da resul­tará no lança­men­to de uma exceção ReferenceError:

var a;
console.log("O valor de a é " + a); // saída "O valor de a é undefined"
console.log("O valor de b é " + b); // executa uma exception de erro de referência (ReferenceError)

Você pode usar undefined para deter­mi­nar se uma var­iáv­el tem um val­or. No códi­go a seguir, não é atribuí­do um val­or de entra­da na var­iáv­el e a declar­ação if será avali­a­da como ver­dadeira (true).

var input;
if(input === undefined){
  facaIsto();
} else {
  facaAquilo();
}

O val­or undefined se com­por­ta como fal­so (false), quan­do usa­do em um con­tex­to booleano. Por exem­p­lo, o códi­go a seguir exe­cu­ta a função myFunction dev­i­do o ele­men­to myArray ser unde­fined:

var myArray = [];
if (!myArray[0]) myFunction();

O val­or undefined con­verte-se para NaN quan­do usa­do no con­tex­to numéri­co.

var a;
a + 2;  // Avaliado como NaN

Quan­do você avalia uma var­iáv­el nula, o val­or nulo se com­por­ta como 0 em con­tex­tos numéri­cos e como fal­so em con­tex­tos booleanos. Por exem­p­lo:

var n = null;
console.log(n * 32); // a saída para o console será 0.

Escopo de variável

Quan­do você declara uma vári­av­el fora de qual­quer função, ela é chama­da de var­iáv­el glob­al, porque está disponív­el para qual­quer out­ro códi­go no doc­u­men­to atu­al. Quan­do você declara uma var­iáv­el den­tro de uma função, é chama­da de var­iáv­el local,  pois ela está disponív­el somente den­tro dessa função.

JavaScript antes do ECMAScript 6 não pos­suía escopo de declar­ação de blo­co; pelo con­trário, uma var­iáv­el declar­a­da den­tro de um blo­co de uma função é uma var­iáv­el local (ou con­tex­to glob­al) do blo­co que está inseri­do a função. Por exem­p­lo o códi­go a seguir exibirá 5, porque o escopo de x está na função (ou con­tex­to glob­al) no qual x é declar­a­do, não o blo­co, que neste caso é a declar­ação if

if (true) {
  var x = 5;
}
console.log(x);  // 5

Esse com­por­ta­men­to é alter­ado, quan­do usa­do a declar­ação let intro­duzi­da pelo ECMAScript 6.

if (true) {
  let y = 5;
}
console.log(y);  // ReferenceError: y não está definido

Variável de elevação

Out­ra coisa inco­mum sobre var­iáveis em JavaScript é que você pode uti­lizar a var­iáv­el e declará-la depois, sem obter uma exceção. Este con­ceito é con­heci­do como hoist­ing; var­iáveis em JavaScript são num sen­ti­do “hoist­ed” ou lança­da para o topo da função ou declar­ação. No entan­to, as var­iáveis que são “hoist­ed” retornarão um val­or undefined. Então, mes­mo se você usar ou referir a var­iáv­el e depois declará-la e ini­cial­izá-la, ela ain­da retornará unde­fined.

/**
 * Exemplo 1
 */
console.log(x === undefined); // exibe "true"
var x = 3;

/**
 * Exemplo 2
 */
// retornará um valor undefined
var myvar = "my value";
 
(function() {
  console.log(myvar); // undefined
  var myvar = "local value";
})();

Os exem­p­los aci­ma serão inter­pre­ta­dos como:

/**
 * Exemplo 1
 */
var x;
console.log(x === undefined); // exibe "true"
x = 3;
 
/**
 * Exemplo 2
 */
var myvar = "um valor";
 
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "valor local";
})();

Dev­i­do o hoist­ing, todas as declar­ações var em uma função devem ser colo­cadas no iní­cio da função. Essa recomen­dação de práti­ca deixa o códi­go mais legív­el.

Variáveis Globais

Var­iáveis globais são pro­priedades do obje­to glob­al. Em pági­nas web o obje­to glob­al é a window, assim você pode con­fig­u­rar e aces­sar var­iáveis globais uti­lizan­do a sin­taxe window.variavel. 

Con­se­quente­mente, você pode aces­sar var­iáveis globais declar­adas em uma janela ou frame ou frame de out­ra janela. Por exem­p­lo, se uma var­iáv­el chama­da pho­neNum­ber é declar­a­da em um doc­u­men­to, você pode con­sul­tar esta var­iáv­el de um frame como parent.phoneNumber.

Constantes

Você pode cri­ar uma con­stante ape­nas de leitu­ra por meio da palavra-chave const. A sin­taxe de um iden­ti­fi­cador de uma con­stante é semel­hante ao iden­ti­fi­cador de uma var­iáv­el: deve começar com uma letra, sub­lin­hado ou cifrão e pode con­ter car­ac­tere alfabéti­co, numéri­co ou sub­lin­hado.

const PI = 3.14;

Uma con­stante não pode alter­ar seu val­or por meio de uma atribuição ou ser declar­a­da nova­mente enquan­to o script está em exe­cução. Deve ser ini­cial­iza­da com um val­or.

As regras de escopo para as con­stantes são as mes­mas para as vári­aveis let de escopo de blo­co. Se a palavra-chave const for omi­ti­da, pre­sume-se que o iden­ti­fi­cador rep­re­sente uma var­iáv­el.

Você não pode declarar uma con­stante com o mes­mo nome de uma função ou var­iáv­el que estão no mes­mo escopo. Por exem­p­lo: 

// Isto irá causar um  erro
function f() {};
const f = 5;

// Isto também irá causar um erro.
function f() {
  const g = 5;
  var g;

  //declarações
}

Estrutura de dados e tipos

Tipos de dados

O mais recente padrão ECMAScript define sete tipos de dados:

  • Seis tipos de dados são os chama­dos prim­i­tivos:
    • Boolean. true e false.
    • null. Uma palavra-chave que indi­ca val­or nulo. Dev­i­do JavaScript ser case-sen­si­tive, null não é o mes­mo que NullNULL, ou ain­da out­ra vari­ação.
    • unde­fined. Uma pro­priedade supe­ri­or cujo val­or é indefinido.
    • Num­ber. 42 ou 3.14159.
    • String. “Howdy”
    • Sym­bol (novo em ECMAScript 6). Um tipo de dado cuja as instân­cias são úni­cas e imutáveis.
  • e Object

Emb­o­ra ess­es tipos de dados sejam uma quan­ti­dade rel­a­ti­va­mente peque­na, eles per­mitem realizar funções úteis em suas apli­cações.  Objetos e funções são out­ros ele­men­tos fun­da­men­tais na lin­guagem. Você pode pen­sar em obje­tos como recip­i­entes para os val­ores, e funções como méto­dos que suas apli­cações podem exe­cu­tar.

Conversão de tipos de dados

JavaScript é uma lin­guagem dinami­ca­mente tipa­da. Isso sig­nifi­ca que você não pre­cisa especi­ficar o tipo de dado de uma var­iáv­el quan­do declará-la, e tipos de dados são con­ver­tidos auto­mati­ca­mente con­forme a neces­si­dade durante a exe­cução do script. Então, por exem­p­lo, você pode definir uma var­iáv­el da seguinte for­ma:

var answer = 42;

E depois, você pode atribuir uma string para a mes­ma var­iáv­el, por exem­p­lo:

answer = "Obrigado pelos peixes...";

Dev­i­do JavaScript ser dinami­ca­mente tipa­do, essa declar­ação não gera uma men­sagem de erro.

Em expressões envol­ven­do val­ores numéri­co e string com o oper­ador +, JavaScript con­verte val­ores numéri­co para strings. Por exem­p­lo, con­sidere a seguinte declar­ação:

x = "A resposta é " + 42 // "A resposta é 42"
y = 42 + " é a resposta" // "42 é a resposta"

Nas declar­ações envol­ven­do out­ros oper­adores,  JavaScript não con­verte val­ores numéri­co para strings. Por exem­p­lo:

"37" - 7 // 30
"37" + 7 // "377"

Convertendo strings para números

No caso de um val­or que rep­re­sen­ta um número está armazena­do na memória como uma string, exis­tem méto­dos para a con­ver­são.

par­seInt irá retornar ape­nas números inteiros, então seu uso é restri­to para a casa dos dec­i­mais. Além dis­so, é uma boa práti­ca ao usar par­seInt incluir o parâmetro da base. O parâmetro da base é usa­do para especi­ficar qual sis­tema númeri­co deve ser usa­do.

Uma méto­do alter­na­ti­vo de con­ver­são de um número em for­ma de string é com o oper­ador + (oper­ador soma):

"1.1" + "1.1" = "1.11.1"
(+"1.1") + (+"1.1") = 2.2   
// Nota: Os parênteses foram usados para deixar mais legível o código, ele não é requirido.

Literais

Você usa lit­erais para rep­re­sen­tar val­ores em JavaScript. Estes são val­ores fix­a­dos, não var­iáveis, que você literalmente insere em seu script. Esta seção descreve os seguintes tipos lit­erais:

  • Array lit­er­al
  • Lit­erais boolean
  • Lit­erais de pon­to flu­tu­ante
  • Inteiros
  • Obje­to lit­er­al
  • String lit­er­al

Array literal

Um array lit­er­al é uma lista de zero ou mais expressões, onde cada uma delas rep­re­sen­tam um ele­men­to do array, inseri­das entre colchetes ([]). Quan­do você cria um array usan­do um array lit­er­al, ele é ini­cial­iza­do  com os val­ores especi­fi­ca­dos como seus ele­men­tos, e seu com­pri­men­to é definido com o  número de ele­men­tos especi­fi­ca­dos.

O exem­p­lo a seguir cria um array coffees com três ele­men­tos e um com­pri­men­to de três:

var coffees = ["French Roast", "Colombian", "Kona"];

Nota : Um array lit­er­al é um tipo de ini­cial­izador de obje­tos. Veja Usan­do ini­cial­izadores de Obje­tos.

Se um array é cri­a­do usan­do um lit­er­al no topo do script, JavaScript inter­pre­ta o array cada vez que avalia a expressão que con­têm o array lit­er­al. Além dis­so, um lit­er­al usa­do em uma função é cri­a­do cada vez que a função é chama­da.

Array lit­er­al são tam­bém um array de obje­tos. Veja  Array e Coleções index­adas para detal­h­es sobre array de obje­tos.

Vírgulas extras em array literal

Você não pre­cisa especi­ficar todos os ele­men­tos em um array lit­er­al. Se você colo­car duas vír­gu­las em uma lin­ha, o array é cri­a­do com undefined para os ele­men­tos não especi­fi­ca­dos. O exem­p­lo a seguir cria um array chama­do fish:

var fish = ["Lion", , "Angel"];

Esse array tem dois ele­men­tos com val­ores e um ele­men­to vazio (fish[0] é “Lion”, fish[1] é undefined, e fish[2] é “Angel” ).

Se você incluir uma vír­gu­la à dire­i­ta no final da lista dos ele­men­tos, a vír­gu­la é igno­ra­da. No exem­p­lo a seguir, o com­pri­men­to do array é três. Não há nen­hum myList[3]. Todas as out­ras vír­gu­las na lista indicam um novo ele­men­to.

Nota : Vír­gu­las à dire­i­ta podem cri­ar erros em algu­mas ver­sões de nave­g­adores web anti­gos, é recomendáv­el removê-las.

var myList = ['home', , 'school', ];

No exem­p­lo a seguir, o com­pri­men­to do array é qua­tro, e myList[0] e myList[2] são undefined.

var myList = [ , 'home', , 'school'];

No exem­p­lo a seguir, o com­pri­men­to do array é qua­tro, e myList[1] e myList[3] são undefined. Ape­nas a últi­ma vír­gu­la é igno­ra­da.

var myList = ['home', , 'school', , ];

Enten­der o com­por­ta­men­to de vír­gu­las extras é impor­tante para a com­preen­são da lin­guagem JavaScript, no entan­to, quan­do você escr­ev­er seu próprio códi­go: declarar explici­ta­mente os ele­men­tos em fal­ta como undefined vai aumen­tar a clareza do códi­go, e con­se­quente­mente na sua manutenção.

Literais Boolean

O tipo Boolean tem dois val­ores lit­er­al: true e false.

Não con­fun­da os val­ores prim­i­tivos Boolean true e false com os val­ores true e false do obje­to Boolean. O obje­to Boolean é um invólu­cro em torno do tipo de dado prim­i­ti­vo. Veja Boolean para mais infor­mação.

Inteiros

Inteiros podem ser expres­sos em dec­i­mal (base 10), hexa­dec­i­mal (base 16), octal (base 8) e binário (base 2).

  • Dec­i­mal inteiro lit­er­al con­siste em uma sequên­cia de dígi­tos sem um 0 (zero).
  • 0 (zero) em um inteiro lit­er­al indi­ca que ele está em octal. Octal pode incluir somente os dígi­tos 0–7.
  • 0x (ou 0X) indi­ca um hexa­dec­i­mal. Inteiros hexa­dec­i­mais podem incluir dígi­tos (0–9) e as letras a‑f e A‑F.
  • 0b (ou 0B) indi­ca um binário. Inteiros binário podem incluir ape­nas os dígi­tos 0 e 1.

Alguns exem­p­los de inteiros lit­er­al são:

0, 117 and -345 (decimal, base 10)
015, 0001 and -077 (octal, base 8) 
0x1123, 0x00111 and -0xF1A7 (hexadecimal, "hex" or base 16)
0b11, 0b0011 and -0b11 (binário, base 2)

Literais de ponto flutuante

Um lit­er­al de pon­to flu­tu­ante pode ter as seguintes partes:

  • Um inteiro dec­i­mal que pode ter sinal (pre­ce­di­do por “+” ou “-”),
  • Um pon­to dec­i­mal (“.”),
  • Uma fração (out­ro número dec­i­mal),
  • Um expoente.

O expoente é um “e” ou “E” segui­do por um inteiro, que pode ter sinal (pre­ce­di­do por “+” ou “-”). Um lit­er­al de pon­to flu­tu­ante  deve ter no mín­i­mo um dígi­to e um pon­to dec­i­mal ou “e” (ou “E”).

Mais sucin­ta­mente, a sin­taxe é:

[(+|-)][digitos][.digitos][(E|e)[(+|-)]digitos]

Por exem­p­lo:

3.1415926
-.123456789
-3.1E+12
.1e-23

Objeto literal

Um obje­to lit­er­al é uma lista de zero ou mais pares de nomes de pro­priedades e val­ores asso­ci­a­dos de um obje­to, colo­ca­do entre chaves ({}). Você não deve usar um obje­to lit­er­al no iní­cio de uma declar­ação. Isso levará a um erro ou não se com­por­tará con­forme o esper­a­do, porque o { será inter­pre­ta­do como iní­cio de um blo­co.

Segue um exem­p­lo de um obje­to lit­er­al. O primeiro ele­men­to do obje­to carro define uma pro­priedade, meuCarro, e atribui para ele uma nova string, “Pun­to”; o segun­do ele­men­to, a pro­priedade getCarro, é ime­di­ata­mente atribuí­do o resul­ta­do de chamar uma função (tipoCarro("Fiat")); o ter­ceiro ele­men­to, a pro­priedade especial, usa uma var­iáv­el exis­tente (vendas).

var vendas = "Toyota";

function tipoCarro(nome) {
  if (nome == "Fiat") {
    return nome;
  } else {
    return "Desculpa, não vendemos carros " + nome + ".";
  }
}

var carro = { meuCarro: "Punto", getCarro: tipoCarro("Fiat"), especial: vendas };

console.log(carro.meuCarro);   // Punto
console.log(carro.getCarro);  // Fiat
console.log(carro.especial); // Toyota

Além dis­so, você pode usar um lit­er­al numéri­co ou string para o nome de uma pro­priedade ou anin­har um obje­to den­tro do out­ro. O exem­p­lo a seguir usar essas opções.

var carro = { carros: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };

console.log(carro.carros.b); // Jeep
console.log(carro[7]); // Mazda

Nomes de pro­priedades de obje­to podem ser qual­quer string, incluin­do uma string vazia. Caso o nome da pro­priedade não seja um iden­ti­fi­cador JavaScript ou número, ele deve ser colo­ca­do entre aspas. Nomes de pro­priedades que não pos­suem iden­ti­fi­cadores váli­do, tam­bém não podem ser aces­sadas pela pro­priedade de pon­to (.), mas podem ser aces­sadas e definidas com a notação do tipo array (“[]”).

var unusualPropertyNames = {
  "": "Uma string vazia",
  "!": "Bang!"
}
console.log(unusualPropertyNames."");   // SyntaxError: string inesperada
console.log(unusualPropertyNames[""]);  // Um string vazia
console.log(unusualPropertyNames.!);    // SyntaxError: símbolo ! inesperado
console.log(unusualPropertyNames["!"]); // Bang!

Observe:

var foo = {a: "alpha", 2: "two"};
console.log(foo.a);    // alpha
console.log(foo[2]);   // two
//console.log(foo.2);  // Error: missing ) after argument list
//console.log(foo[a]); // Error: a não está definido
console.log(foo["a"]); // alpha
console.log(foo["2"]); // two

Expressão Regex Literal

Um regex lit­er­al é um padrão entre bar­ras. A seguir um exem­p­lo de regex lit­er­al.

var re = /ab+c/;

String Literal

Uma string lit­er­al são zero ou mais car­ac­teres dis­pos­tos em aspas duplas (") ou aspas sim­ples ('). Uma sequên­cia de car­ac­teres deve ser delim­i­ta­da por aspas do mes­mo tipo; ou seja,  as duas aspas sim­ples ou ambas aspas duplas. A seguir um exem­p­lo de strings lit­erais.

"foo"
'bar'
"1234"
"um linha \n outra linha"
"John's cat"

Você pode chamar qual­quer um dos méto­dos do obje­to string em uma string lit­er­al — JavaScript auto­mati­ca­mente con­verte a string lit­er­al para um obje­to string tem­porário, chama o méto­do, em segui­da, descar­ta o obje­to string tem­porário. Você tam­bém pode usar a pro­priedade String.length com uma string lit­er­al:

console.log("John's cat".length) 
// Irá exibir a quantidade de caracteres na string incluindo o espaço em branco. 
// Nesse caso, 10 caracteres.

Você deve usar string lit­er­al, a não ser que você pre­cise usar um obje­to string. Veja String para detal­h­es sobre obje­tos de strings.

Uso de caracteres especiais em string

Além dos car­ac­teres comuns, você tam­bém pode incluir car­ac­teres espe­ci­ais em strings, como mostra­do no exem­p­lo a seguir.

"uma linha \n outra linha"

A tabela a seguir lista os car­ac­teres espe­ci­ais que podem ser usa­dos em strings no JavaScript.

Car­ac­terDescrição
\0Byte nulo
\bBack­space
\fAli­men­ta­dor de for­mulário
\nNova lin­ha
\rRetorno do car­ro
\tTab­u­lação
\vTab­u­lação ver­ti­cal
\'Apóstro­fo ou aspas sim­ples
\"Aspas dupla
\\Car­ac­tere de bar­ra inver­ti­da
\XXXCar­ac­tere com a cod­i­fi­cação Latin‑1 especi­fi­ca­da por três dígi­tos octal XXX entre 0 e 377. Por exem­p­lo, \251 é sequên­cia octal para o sím­bo­lo de dire­itos autorais.
\xXXCar­ac­tere com a cod­i­fi­cação Latin‑1 especi­fi­ca­da por dois dígi­tos hexa­dec­i­mal XX entre 00 e FF. Por exem­p­lo, \xA9 é a sequên­cia hexa­dec­i­mal para o sím­bo­lo de dire­itos autorais.
\uXXXXCar­ac­tere Uni­code especi­fi­ca­do por qua­tro dígi­tos hexa­dec­i­mal XXXX. Por exem­p­lo, \u00A9 é a sequên­cia Uni­code para o sím­bo­lo de dire­itos autorais.

Caracteres de escape

Para car­ac­teres não lis­ta­dos na tabela, se pre­ce­di­dos de bar­ra inver­ti­da ela é igno­ra­da, seu uso está abso­le­to e deve ser igno­ra­do.

Você pode inserir uma aspa den­tro de uma string precendendo‑a com uma bar­ra inver­ti­da. Isso  é con­heci­do como escap­ing das aspas. Por exem­p­lo:

var quote = "Ele lê \"The Cremation of Sam McGee\" de R.W. Service.";
console.log(quote);

O resul­ta­do dis­so seria:

Ele lê "The Cremation of Sam McGee" de R.W. Service.

Para incluir uma bar­ra inver­ti­da den­tro de uma string, você deve escapar o car­ac­tere de bar­ra inver­ti­da. Por exem­p­lo, para atribuir o cam­in­ho do arqui­vo c:\temp para uma string, uti­lize o seguinte:

var home = "c:\\temp";

Você tam­bém pode escapar que­bras de lin­has, prece­den­do-as com bar­ra inver­ti­da. A bar­ra inver­ti­da e a que­bra de lin­ha são ambas removi­das da string.

var str = "esta string \
está quebrada \
em várias\
linhas."
console.log(str);   // esta string está quebrada em várias linhas.

Emb­o­ra JavaScript não ten­ha sin­taxe “here­doc”, você pode adi­cionar uma que­bra de lin­ha e um escape de que­bra de lin­ha no final de cada lin­ha:

var poema = 
"Rosas são vermelhas\n\
Violetas são azuis,\n\
Esse seu sorriso\n\
é o que me seduz. (Lucas Pedrosa)"

Declaração em bloco

Uma declar­ação em blo­co é uti­liza­da para agru­par declar­ações. O blo­co é delim­i­ta­do por um par de chaves:

{
   declaracao_1;
   declaracao_2;
   .
   .
   .
   declaracao_n;
}

Exemplo

Declar­ações em blo­co são uti­lizadas geral­mente com declar­ações de fluxo de con­t­role (ex. ifforwhile).

while (x < 10) {
  x++;
}

Aqui, { x++; } é a declar­ação de blo­co.

Impor­tante: Antes de ECMAScript 6 o JavaScript não pos­suía escopo de blo­co. Var­iáveis intro­duzi­das den­tro de um blo­co pos­suem como escopo a função ou o script em que o blo­co está con­ti­do, e, definir tais var­iáveis tem efeito muito além do blo­co em si. Em out­ras palavras, declar­ações de blo­co não intro­duzem um escopo. Emb­o­ra blo­cos “padrão” sejam uma sin­taxe vál­i­da não uti­lize-os, em JavaScript, pen­san­do que fun­cionam como em C ou Java porque eles não fun­cionam da maneira que você acred­i­ta. Por exem­p­lo:

var x = 1;
{
  var x = 2;
}
console.log(x); // exibe 2

Este códi­go exibe 2 porque a declar­ação var x den­tro do blo­co pos­sui o mes­mo escopo que a declar­ação var x antes do blo­co. Em C ou Java, o códi­go equiv­a­lente exibiria 1.

Declarações condicionais

Uma declar­ação condi­cional é um con­jun­to de coman­dos que são exe­cu­ta­dos caso uma condição especi­fi­ca­da seja ver­dadeira. O JavaScript supor­ta duas declar­ações condi­cionais: if...else e switch.

Declaração if…else

Use a declar­ação if para exe­cu­tar algu­ma declar­ação caso a condição lóg­i­ca for ver­dadeira. Use a cláusu­la opcional else para exe­cu­tar algu­ma declar­ação caso a condição lóg­i­ca for fal­sa. Uma declar­ação if é declar­a­da da seguinte maneira:

if (condicao) {
  declaracao_1;
} else {
  declaracao_2;
}

onde condicao pode ser qual­quer expressão que seja avali­a­da como ver­dadeira ou fal­sa. Veja Boolean para uma expli­cação sobre o que é avali­a­do como true e false. Se condicao for avali­a­da como ver­dadeira, declar­a­cao_1 é exe­cu­ta­da; caso con­trário, declaracao_2 é exe­cu­ta­da. declaracao_1 e declaracao_2 podem ser qual­quer declar­ação, incluin­do declar­ações if anin­hadas.

Você pode tam­bém com­bi­nar declar­ações uti­lizan­do else if para obter várias condições tes­tadas em sequên­cia, como o seguinte:

if (condicao) {
  declaracao_1;
} else if (condicao_2) {
  declaracao_2;
} else if (condicao_n) {
  declaracao_n;
} else {
  declaracao_final;
}

Para exe­cu­tar várias declar­ações, agrupe-as em uma declar­ação em blo­co ({ ... }). Em ger­al, é uma boa práti­ca sem­pre uti­lizar declar­ações em blo­co, espe­cial­mente ao anin­har declar­ações if:

if (condicao) {
    declaracao_1_executada_se_condicao_for_verdadeira;
    declaracao_2_executada_se_condicao_for_verdadeira;
} else {
    declaracao_3_executada_se_condicao_for_falsa;
    declaracao_4_executada_se_condicao_for_falsa;
}

Recomen­da-se não uti­lizar atribuições sim­ples em uma expressão condi­cional porque o sím­bo­lo de atribuição pode­ria ser con­fun­di­do com o de igual­dade ao dar uma olha­da no códi­go. Por exem­p­lo, não uti­lize o seguinte códi­go:

if (x = y) {
  /* faça a coisa certa */
}

Caso ten­ha que uti­lizar uma atribuição em uma expressão condi­cional, uma práti­ca comum é colo­car parên­te­ses adi­cionais em vol­ta da atribuição. Por exem­p­lo:

if ((x = y)) {
  /* faça a coisa certa */
}

Valores avaliados como falsos

Os seguintes val­ores são avali­a­dos como fal­sos:

  • false
  • undefined
  • null
  • 0
  • NaN
  • string vazia ("")

Todos os out­ros val­ores, incluin­do todos os obje­tos, são avali­a­dos como ver­dadeiros quan­do pas­sa­dos para uma declar­ação condi­cional.

Não con­fun­da os val­ores booleanos prim­i­tivos true e false com os val­ores de true e false do obje­to Boolean. Por exem­p­lo:

var b = new Boolean(false);
if (b) // esta condição é avaliada como verdadeira
if (b == true) // esta condição é avaliada como falsa

Exemplo

No exem­p­lo a seguir, a função verifiqueDados retor­na ver­dadeiro se o número de car­ac­teres em um obje­to Text for três; caso con­trário, exibe um aler­ta e retor­na falso.

function verifiqueDados() {
  if (document.form1.tresCaracteres.value.length == 3) {
    return true;
  } else {
    alert("Informe exatamente três caracteres. " +
      document.form1.tresCaracteres.value + " não é válido.");
    return false;
  }
}

Declaração switch

Uma declar­ação switch per­mite que um pro­gra­ma ava­lie uma expressão e tente asso­ciar o val­or da expressão ao rótu­lo de um case. Se uma cor­re­spondên­cia é encon­tra­da, o pro­gra­ma exe­cu­ta a declar­ação asso­ci­a­da. Uma declar­ação switch se parece com o seguinte:

switch (expressao) {
   case rotulo_1:
      declaracoes_1
      

[break;]

case rotulo_2: declaracoes_2

[break;]

… default: declaracoes_padrao

[break;]

}

O pro­gra­ma primeira­mente procu­ra por uma cláusu­la case com um rótu­lo que cor­re­spon­da ao val­or da expressão e então trans­fere o con­t­role para aque­la cláusu­la, exe­cu­tan­do as declar­a­coes asso­ci­adas. Se nen­hum rótu­lo cor­re­spon­dente é encon­tra­do, o pro­gra­ma procu­ra pela cláusu­la opcional default e, se encon­tra­da, trans­fere o con­t­role àquela cláusu­la, exe­cu­tan­do as declar­ações asso­ci­adas. Se nen­hu­ma cláusu­la default é encon­tra­da, o pro­gra­ma con­tin­ua a exe­cução a par­tir da declar­a­cao seguinte ao switch. Por con­venção, a cláusu­la default é a últi­ma, mas não é necessário que seja assim.

A instrução break asso­ci­a­da a cada cláusu­la case, garante que o pro­gra­ma sairá do switch assim que a declar­ação cor­re­spon­dente for exe­cu­ta­da e que con­tin­uará a exe­cução a par­tir da declar­ação seguinte ao switch. Se a declar­ação break for omi­ti­da, o pro­gra­ma con­tin­ua a exe­cução a par­tir da próx­i­ma declar­ação den­tro do switch.

Exemplo

No exem­p­lo a seguir, se tipofruta for avali­a­da como “Banana”, o pro­gra­ma faz a cor­re­spondên­cia do val­or com case Banana” e exe­cu­ta a declar­ação asso­ci­a­da. Quan­do o break é encon­tra­do, o pro­gra­ma ter­mi­na o switch e exe­cu­ta a declar­ação seguinte ao condi­cional. Se o break fos­se omi­ti­do, a declar­ação de case Cereja” tam­bém seria exe­cu­ta­da.

switch (tipofruta) {
   case "Laranja":
      console.log("O quilo da laranja está R$0,59.<br>");
      break;
   case "Maçã":
      console.log("O quilo da maçã está R$0,32.<br>");
      break;
   case "Banana":
      console.log("O quilo da banana está R$0,48.<br>");
      break;
   case "Cereja":
      console.log("O quilo da cereja está R$3,00.<br>");
      break;
   case "Manga":
      console.log("O quilo da manga está R$0,56.<br>");
       break;
   case "Mamão":
      console.log("O quilo do mamão está R$2,23.<br>");
      break;
   default:
      console.log("Desculpe, não temos " + tipofruta + ".<br>");
}
console.log("Gostaria de mais alguma coisa?<br>");

Declarações de Manipulação de Error

Você pode chamar uma exceção usan­do a declar­ação throw e manip­ulá-la usan­do a declar­ação try...catch.

  • Declar­ação throw
  • Declar­ação try...catch

Tipos de exceções

Prati­ca­mente pode-se uti­lizar throw em qual­quer obje­to de JavaScript. Todavia, nem todos os obje­tos ati­va­dos por throw são igual­mente cri­a­dos. Emb­o­ra seja bas­tante comum tratar números ou strings como erros usan­do throw, é fre­quente­mente mais efi­ciente usar alguns tipos de exceções especi­fi­ca­mente cri­adas para ess­es propósi­tos:

Declaração throw

Use a declar­ação throw para lançar uma exceção. Quan­do você lança uma exceção, você especi­fi­ca a expressão con­tendo o val­or a ser lança­do:

throw expressão;

Você pode lançar qual­quer expressão, não ape­nas expressões de um tipo especí­fi­co. O códi­go a seguir lança várias exceções de difer­entes tipos:

throw "Error2";   // tipo string
throw 42;         // tipo numérico
throw true;       // tipo booleano
throw {toString: function() { return "Eu sou um objeto!"; } };

Nota:  Você pode especi­ficar um obje­to quan­do você lança uma exceção. Você pode então, ref­er­en­ciar as pro­priedades de um obje­to no blo­co catch.  O exem­p­lo a seguir cria um obje­to myUserEx­cep­tion do tipo userEx­cep­tion e o usa em uma declar­ação throw.

// Cria um objeto do tipo UserException
function UserException(mensagem) {
  this.mensagem = mensagem;
  this.nome = "UserException";
}

// Realiza a conversão da exceção para uma string adequada quando usada como uma string.
// (ex. pelo console de erro)
UserException.prototype.toString = function() {
  return this.name + ': "' + this.message + '"';
}

// Cria uma instância de um tipo de objeto e lança ela
throw new UserException("Valor muito alto");

Declaração try...catchSeção

A declar­ação try...catch colo­ca um blo­co de declar­ações em try, e especi­fi­ca uma ou mais respostas para uma exceção lança­da. Se uma exceção é lança­da, a declar­ação try...catch pegá‑a.

A declar­ação try...catch é com­pos­ta por um blo­co try, que con­tém uma ou mais declar­ações, e zero ou mais blo­cos catch, con­tendo declar­ações que especi­fi­cam o que faz­er se uma exceção é lança­da no blo­co try. Ou seja, você dese­ja que o blo­co try  ten­ha suces­so, e se ele não tiv­er êxi­to, você quer o con­t­role pas­sa­do para o blo­co catch. Se qual­quer declar­ação do blo­co try (ou em uma função chama­da den­tro do blo­co try) lança uma exceção, o con­t­role é ime­di­ata­mente muda­do para o blo­co catch. Se nen­hu­ma exceção é lança­da no blo­co try, o blo­co catch é igno­ra­do. O blo­co finally exe­cu­ta após os blo­cos try e catch exe­cutarem, mas antes das declar­ações seguinte ao blo­co try...catch.

O exem­p­lo a seguir usa a declar­ação try...catch. O exem­p­lo chama uma função que recu­pera o nome de um mês no array com base no val­or pas­sa­do para a função. Se o val­or não cor­re­sponde ao número de um mês (1–12), uma exceção é lança­da com o val­or “InvalidMonthNo” e as declar­ações no blo­co catch define a vári­av­el monthName para unknown.

function getMonthName(mo) {
  mo = mo - 1; // Ajusta o número do mês para o índice do array (1 = Jan, 12 = Dec)
  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul",
                "Aug","Sep","Oct","Nov","Dec"];
  if (months[mo]) {
    return months[mo];
  } else {
    throw "InvalidMonthNo"; //lança uma palavra-chave aqui usada.
  }
}

try { // statements to try
  monthName = getMonthName(myMonth); // função poderia lançar uma exceção
}
catch (e) {
  monthName = "unknown";
  logMyErrors(e); // passa a exceção para o manipulador de erro -> sua função local.
}

O bloco catch

Você pode usar um blo­co catch para lidar com todas as exceções que podem ser ger­adas no blo­co try.

catch (catchID) {
  declaracoes
}

O blo­co catch especí­fi­ca um iden­ti­fi­cador (catchID na sin­taxe ante­ri­or), que con­tém o val­or especi­fi­ca­do pela declar­ação throw; você pode usar esse iden­ti­fi­cador para obter infor­mações sobre a exceção que foi lança­da. JavaScript cria este iden­ti­fi­cador quan­do o blo­co catch é inseri­do; o iden­ti­fi­cador dura enquan­to o blo­co catch está em exe­cução, depois que ter­mi­na a exe­cução do blo­co catch, o iden­ti­fi­cador não estará mais disponív­el.

Por exem­p­lo, o seguinte códi­go lança uma exceção. Quan­do a exceção ocorre, o con­t­role é trans­feri­do para o blo­co catch.

try {
  throw "myException"; // lança  uma exceção
}
catch (e) {
  // declarações de lidar com as exceções
  logMyErrors(e); // passar a exceção para o manipulador de erro
}

O bloco finally

O blo­co finally con­tém instruções para exe­cu­tar após os blo­cos try e catch, mas antes das declar­ações seguinte a declar­ação try...catch. O blo­co finally é exe­cu­ta­do com ou sem o lança­men­to de uma exceção. Se uma exceção é lança­da, a declar­ação no blo­co finally exe­cu­ta, mes­mo que nen­hum blo­co catch processe a exceção.

Você pode usar blo­co finally para deixar a fal­ha de seu script agradáv­el quan­do uma exceção ocorre; por exem­p­lo, você pode pre­cis­ar lib­er­ar um recur­so que seu script tem amar­ra­do. O exem­p­lo a seguir abre um arqui­vo e então exe­cu­ta instruções que usam o arqui­vo (JavaScript do lado do servi­dor per­mite que você acesse arquiv­os). Se um exceção é lança­da enquan­to o arqui­vo é aber­to, o blo­co finally fecha o arqui­vo antes do script fal­har.

openMyFile();
try {
  writeMyFile(theData); //Isso pode lançar um erro
} catch(e) {  
  handleError(e); // Se temos um erro temos que lidar com ele
} finally {
  closeMyFile(); // Sempre feche o recurso
}

Se o blo­co finally retornar um val­or, este val­or se tor­na o val­or de toda a entra­da try-catch-finally, inde­pen­dente de quais­quer declar­ações de retorno nos blo­cos try e catch:

function f() {
  try {
    console.log(0);
    throw "bogus";
  } catch(e) {
    console.log(1);
    return true; // essa declaração de retorno é suspensa
                 // até que o bloco finally seja concluído
    console.log(2); // não executa
  } finally {
    console.log(3);
    return false; // substitui o "return" anterior
    console.log(4); // não executa
  }
  // "return false" é executado agora 
  console.log(5); // não executa
}
f(); // exibe 0, 1, 3; retorna false

Sub­sti­tu­ições de val­ores de retorno pelo blo­co finally tam­bém se apli­ca a exceções lançadas ou re-lançadas den­tro do blo­co catch:

function f() {
  try {
    throw "bogus";
  } catch(e) {
    console.log('captura interior "falso"');
    throw e; // essa instrução throw é suspensa até 
             // que o bloco finally seja concluído
  } finally {
    return false; // substitui "throw" anterior
  }
  // "return false" é executado agora
}

try {
  f();
} catch(e) {
  // isto nunca é executado porque o throw dentro
  // do catch é substituído
  // pelo return no finally
  console.log('captura exterior "falso"');
}

// SAIDA
// captura interior "falso"

Aninhando declarações try…catch

Você pode anin­har uma ou mais declar­ações try...catch. Se uma declar­ação try...catch inte­ri­or não tem um blo­co catch, o delim­i­ta­dor do blo­co try...catch da declar­ação catch é ver­i­fi­ca­do por uma cor­re­spondên­cia.

Utilizando objetos de erro

Depen­den­do do tipo de erro, você pode ser capaz de usar as pro­priedade ‘name’ e ‘mes­sage’ para pegar uma men­sagem mais refi­na­da. A pro­priedade ‘name’ fornece a classe ger­al de erro (ex., ‘DOMEx­cep­tion’ ou ‘Error’), enquan­to ‘mes­sage’ geral­mente ofer­ece uma men­sagem mais sucin­ta do que se pode­ria obter através da con­ver­são do obje­to de erro para uma string.

Se você está lançan­do suas próprias exceções, a fim de tirar proveito dessas pro­priedades (como o seu blo­co catch não dis­crim­i­na entre suas próprias exceções e as exceções próprias da lin­guagem), você pode usar o con­stru­tor Error. Por exem­p­lo:

function doSomethingErrorProne () {
  if (ourCodeMakesAMistake()) {
    throw (new Error('A mensagem'));
  } else {
    doSomethingToGetAJavascriptError();
  }
}
....
try {
  doSomethingErrorProne();
}
catch (e) {
  console.log(e.name); // exibe 'Error'
  console.log(e.message); // exibe 'A mensagem' ou uma mensagem de erro em JavaScript
}

Promises

Começan­do com ECMAScript 6, JavaScript gan­ha suporte para obje­tos Promise que lhe per­mite con­tro­lar o fluxo de oper­ações difer­í­das e assín­cronas.

Uma Promise assume um destes esta­dos:

  • pend­ing: esta­do ini­cial, não fulfilled, ou rejected.
  • ful­filled: oper­ação bem suce­di­da.
  • reject­ed: oper­ação fal­ha.
  • set­tled: A Promise é ful­filled ou reject­ed, mas não pend­ing.

Carregando uma imagem com XHRSeção

Um exem­p­lo sim­ples usan­do Promise e XMLHttpRequest para carregar uma imagem disponível no repositório MDN GitHub promise-test. Você tam­bém pode vê-lo exe­cu­tan­do. Cada eta­pa está comen­ta­da o que lhe per­mite seguir de per­to a arquite­tu­ra Promise e arquite­tu­ra XHR. Aqui está a ver­são não comen­ta­da, mostran­do o fluxo Promise para que você pos­sa ter uma ideia:

function imgLoad(url) {
  return new Promise(function(resolve, reject) {
    var request = new XMLHttpRequest();
    request.open('GET', url);
    request.responseType = 'blob';
    request.onload = function() {
      if (request.status === 200) {
        resolve(request.response);
      } else {
        reject(Error('Image didn\'t load successfully; error code:' 
                     + request.statusText));
      }
    };
    request.onerror = function() {
      reject(Error('There was a network error.'));
    };
    request.send();
  });
}

.

Laços ofer­e­cem um jeito fácil e rápi­do de exe­cu­tar uma ação repeti­das vezes. Este capí­tu­lo abor­dará difer­entes for­mas de iter­ações exis­tentes no JavaScript.

Você pode pen­sar em um laço de repetição como um jogo onde você man­da o seu per­son­agem andar X pas­sos em uma direção e Y pas­sos em out­ra; por exem­p­lo, a ideia “vá 5 pas­sos para leste” pode ser expres­sa em um laço des­ta for­ma:

var passo;
for (passo = 0; passo < 5; passo++) {
  // Executa 5 vezes, com os valores de passos de 0 a 4.
  console.log('Ande um passo para o leste');
}

Exis­tem várias for­mas difer­entes de laços, mas eles essen­cial­mente fazem a mes­ma coisa: repe­tir uma ação múlti­plas vezes ( inclu­sive você poderá repe­tir 0 vezes). Os vários mecan­is­mos difer­entes de laços ofer­e­cem difer­entes for­mas de deter­mi­nar quan­do este irá começar ou ter­mi­nar. Há várias situ­ações em que é mais fácil resolver um prob­le­ma uti­lizan­do um deter­mi­na­do tipo de laço do que out­ros.

Os pos­síveis laços de repetição  em JavaScript:

  • for_statement
  • do…while_statement
  • while_statement
  • label_statement
  • break_statement
  • continue_statement
  • for…in_statement
  • for…of_statement

Declaração for

Um laço for é repeti­do até que a condição especi­fi­ca­da seja fal­sa. O laço for no JavaScript é sim­i­lar ao Java e C. Uma declar­ação for é fei­ta da seguinte maneira:

for ([expressaoInicial]; [condicao]; [incremento])
  declaracao

Quan­do um for é exe­cu­ta­do, ocorre o seguinte:

  1. A expressão expressao Inicial é ini­cial­iza­da e, caso pos­sív­el, é exe­cu­ta­da. Nor­mal­mente essa expressão ini­cial­iza um ou mais con­ta­dores, mas a sin­taxe per­mite expressões de qual­quer grau de com­plex­i­dade. Poden­do con­ter tam­bém declar­ação de var­iáveis.
  2. A expressão condicao é avali­a­da. caso o resul­ta­do de condicao seja ver­dadeiro, o laço é exe­cu­ta­do. Se o val­or de condicao é fal­so, então o laço ter­mi­nará. Se a expressão condicao é omi­ti­da, a condicao é assum­i­da como ver­dadeira.
  3.  A instrução é exe­cu­ta­da. Para exe­cu­tar múlti­plas declar­ações, use uma declar­ação em blo­co ({ … }) para agrupá-las.
  4. A atu­al­iza­ção da expressão incremento, se hou­ver, exe­cu­ta, e retor­na o con­t­role para o pas­so 2.

Exemplo

A função a seguir con­tém uma declar­ação for que con­tará o número de opções sele­cionadas em uma lista (um ele­men­to <select> per­mite várias seleções). Den­tro do for é declar­a­do uma vári­av­el i ini­cial­iza­da com zero. A declar­ação for ver­i­fi­ca se i é menor que o número de opções no ele­men­to <select>, exe­cu­ta suces­si­vas declar­ação  if, e incre­men­ta i de um em um a cada pas­sagem pelo laço.

<form name="selectForm">
  <p>
    <label for="tipoMusica">Escolha alguns tipos de música, em seguida, clique no botão abaixo:</label>
    <select id="tipoMusica" name="tipoMusica" multiple="multiple">
      <option selected="selected">R&B</option>
      <option>Jazz</option>
      <option>Blues</option>
      <option>New Age</option>
      <option>Classico</option>
      <option>Ópera</option>
    </select>
  </p>
  <p><input id="btn" type="button" value="Quantos foram selecionados?" /></p>
</form>

<script>
function howMany(selectObject) {
  var numeroSelecionadas = 0;
  for (var i = 0; i < selectObject.options.length; i++) {
    if (selectObject.options[i].selected) {
      numeroSelecionadas++;
    }
  }
  return numeroSelecionadas;
}

var btn = document.getElementById("btn");
btn.addEventListener("click", function(){
  alert('Total de opções selecionadas: ' + howMany(document.selectForm.tipoMusica))
});
</script>

Declaração do...while

A instrução do…while repe­tirá até que a condição especi­fi­ca­da seja fal­sa.

do
  declaracao
while (condicao);

A instrução será exe­cu­ta­da uma vez antes da condição ser ver­i­fi­ca­da. Para exe­cu­tar mul­ti­plas instruções uti­lize uma declar­ação de blo­co ({ … }) para agrupá-las. Caso a condicao seja ver­dadeira, então o laço será exe­cu­ta­do nova­mente. Ao final de cada exe­cução, a condicao é ver­i­fi­ca­da. Quan­do a condição con­ti­da no while for fal­sa a exe­cução do laço é ter­mi­na­da e o con­t­role é pas­sa­do para a instrução seguinte a do...while.

Exemplo

No exem­p­lo a seguir, o laço é exe­cu­ta­do pelo menos uma vez e irá exe­cu­tar até que i seja menor que 5.

do {
  i += 1;
  console.log(i);
} while (i < 5);

Declaração while

Uma declar­ação while exe­cu­ta suas instruções, des­de que uma condição especi­fi­ca­da seja avali­a­da como ver­dadeira. Segue uma declar­ação while

while (condicao)
  declaracao

Se a condição se tornar fal­sa,  a declar­ação den­tro do laço para a exe­cução e o con­t­role é pas­sa­do para a instrução após o laço.

O teste da condição ocorre antes que o laço seja exe­cu­ta­do. Des­ta for­ma se a condição for ver­dadeira o laço exe­cu­tará e tes­tará a condição nova­mente. Se a condição for fal­sa o laço ter­mi­na e pas­sa o con­t­role para as instruções após o laço.

Para exe­cu­tar múlti­plas declar­ações, use uma declar­ação em blo­co ({ … }) para agru­par essas declar­ações.

Exemplo 1

while a seguir exe­cu­tará enquan­to n for menor que três:

n = 0;
x = 0;
while (n < 3) {
  n++;
  x += n;
}

A cada iter­ação, o laço incre­men­ta n e adi­ciona este val­or para x. Por­tan­to, x e n recebem os seguintes val­ores:

  • Depois de exe­cu­tar pela primeira vez: n = 1 e x = 1
  • Depois da segun­da vez: n = 2 e x = 3
  • Depois da ter­ceira vez: n = 3 e x = 6

Depois de exe­cu­tar pela ter­ceira vez, a condição n < 3 não será mais ver­dadeira, então o laço encer­rará.

Exemplo 2

Evite laços infini­tos. Ten­ha certeza que a condição do laço even­tual­mente será fal­sa; caso con­trário, o laço nun­ca ter­mi­nará. O while a seguir exe­cu­tará para sem­pre pois sua condição nun­ca será fal­sa:

while (true) {
  console.log("Olá, mundo");
}

Declaração label

Um label provê um iden­ti­fi­cador que per­mite que este seja ref­er­en­ci­a­do em out­ro lugar no seu pro­gra­ma. Por exem­p­lo, você pode usar uma label para iden­ti­ficar um laço, e então usar break ou continue para indicar quan­do o pro­gra­ma dev­erá inter­romper o laço ou con­tin­uar sua exe­cução.

Segue a sin­taxe da instrução label:

label : declaracao

Um label pode usar qual­quer iden­fi­cador que não seja uma palavra reser­va­da do JavaScript. Você pode iden­ti­ficar qual­quer instrução com um label.

Exemplo

Neste exem­p­lo, o label markLoop iden­fi­ca um laço while.

markLoop:
while (theMark == true) {
   facaAlgo();
}

Declaração break

Use break para ter­mi­nar laços, switch, ou um con­jun­to que uti­liza label.

  • Quan­do você uti­liza break sem um label, ele encer­rará ime­di­ata­mente o laço mais inter­no whiledo-whilefor, ou switch e trans­ferirá o con­t­role para a próx­i­ma instrução.
  • Quan­do você uti­liza break com um label, ele encer­rará o label especí­fi­co.

Segue a sin­taxe do break:

  1. break;
  2. break label;

Na primeira opção será encer­ra­do o laço de repetição mais inter­no ou switch. Já na segun­da opção será encer­ra­da o blo­co de códi­go ref­er­ente a label.

Exemplo 1

O exem­p­lo a seguir per­corre os ele­men­tos de um array até que ele encon­tre o índice do ele­men­to que pos­sui o val­or con­ti­do em theValue:

for (i = 0; i < a.length; i++) {
  if (a[i] == theValue) {
    break;
  }
}

Exemplo 2: Utilizando break em label

var x = 0;
var z = 0
labelCancelaLaco: while (true) {
  console.log("Laço exterior: " + x);
  x += 1;
  z = 1;
  while (true) {
    console.log("Laço interior: " + z);
    z += 1;
    if (z === 10 && x === 10) {
      break labelCancelaLaco;
    } else if (z === 10) {
      break;
    }
  }
}

Declaração continue

A declar­ação con­tin­ue pode ser usa­da para reini­ciar uma instrução whiledo-whilefor, ou label.

  • Quan­do você uti­liza continue sem uma label, ele encer­rará a iter­ação atu­al mais inter­na de uma instrução whiledo-while, ou for e con­tin­uará a exe­cução do laço a par­tir da próx­i­ma iter­ação. Ao con­trário da instrução breakcontinue não encer­ra a exe­cução com­ple­ta do laço. Em um laço while, ele voltará para a condição. Em um laço for, ele pulará para a expressão de incre­men­tação.
  • Quan­do você uti­liza continue com uma label, o continue será apli­ca­do ao laço iden­ti­fi­ca­do por esta label. 

Segue a sin­taxe do continue:

  1. continue;
  2. continue label;

Exemplo 1

O exem­p­lo a seguir mostra um laço while utl­izan­do continue que exe­cu­tará quan­do o val­or de i for igual a 3. Des­ta for­ma, n recebe os val­ores um, três, sete, e doze.

i = 0;
n = 0;
while (i < 5) {
  i++;
  if (i == 3) {
    continue;
  }
  n += i;
}

Exemplo 2

Uma instrução label checkiandj con­tém uma instrução label checkj. Se o continue for exe­cu­ta­do, o pro­gra­ma ter­mi­nará a iter­ação atu­al de checkj e começará a próx­i­ma iter­ação. Toda vez que o continue for exe­cu­ta­do, checkj recomeçará até que a condição do while for fal­sa. Quan­do isto ocor­rer checkiandj exe­cu­tará até que sua condição seja fal­sa.

Se o continue estivesse ref­er­en­cian­do checkiandj, o pro­gra­ma dev­e­ria con­tin­uar do topo de checkiandj.

checkiandj:
  while (i < 4) {
    console.log(i);
    i += 1;
    checkj:
      while (j > 4) {
        console.log(j);
        j -= 1;
        if ((j % 2) == 0) {
          continue checkj;
        }
        console.log(j + " é estranho.");
      }
      console.log("i = " + i);
      console.log("j = " + j);
  }

Declaração for...in

A declar­ação for…in exe­cu­ta iter­ações a par­tir de uma var­iáv­el especí­fi­ca, per­cor­ren­do todas as pro­priedades de um obje­to.
Para cada pro­priedade dis­tin­ta, o JavaScript exe­cu­tará uma iter­ação. Segue a sin­taxe:

for (variavel in objeto) {
  declaracoes
}

Exemplo

A função a seguir recebe em seu argu­men­to um obje­to e o nome deste obje­to. Então exe­cu­tará uma iter­ação para cada ele­men­to e retornará uma lista de string, que irá con­ter o nome da pro­priedade e seu val­or.

function dump_props(obj, obj_name) {
  var result = "";
  for (var i in obj) {
    result += obj_name + "." + i + " = " + obj[i] + "<br>";
  }
  result += "<hr>";
  return result;
}

Para um obje­to chama­do car com pro­priedades make e model, o resul­ta­do será:

car.make = Ford
car.model = Mustang

Arrays

Emb­o­ra seja ten­ta­dor usar esta for­ma para inter­a­gir com os ele­men­tos de um Array, a declar­ação for…in irá retornar o nome pré-definido da pro­priedade ao invés do seu index numéri­co. Assim é mel­hor usar o tradi­cional for com index numéri­co quan­do inter­a­gir com arrays, pois o for…in inter­age com as pro­priedades definidas pelo pro­gra­mador ao invés dos ele­men­tos do array.

Declaração for...of

 A declar­ação for…of cria uma laço com obje­tos inter­a­tivos ((incluin­do, ArrayMapSet, assim por con­seguinte ), exe­cu­tan­do uma iter­ação para o val­or de cada pro­priedade dis­tin­ta.

for (variavel of objeto) {
  declaracoes
}

O exem­p­lo a seguir mostra a difer­ença entre o for...of e o for...in. Enquan­to o for...in inter­age com o nome das pro­priedades, o for...of inter­age com o val­or das pro­priedades.

let arr = [3, 5, 7];
arr.foo = "hello";

for (let i in arr) {
   console.log(i); // logs "0", "1", "2", "foo"
}

for (let i of arr) {
   console.log(i); // logs "3", "5", "7"
}

Definindo Funções

definição da função (tam­bém chama­da de declar­ação de função) con­siste no uso da palavra chave function, segui­da por:

  • Nome da Função.
  • Lista de argu­men­tos para a função, entre parên­te­ses e sep­a­ra­dos por vír­gu­las.
  • Declar­ações JavaScript que definem a função, entre chaves { }.

Por exem­p­lo, o códi­go a seguir define uma função sim­ples chama­da square:

function square(numero) { 
  return numero * numero; 
}

A função square recebe um argu­men­to, chama­do numero. A função con­siste em uma instrução que indi­ca para retornar o argu­men­to da função (isto é, numero) mul­ti­pli­ca­do por si mes­mo. A declar­ação return especi­fi­ca o val­or retor­na­do pela função.

return numero * numero;

Parâmet­ros prim­i­tivos (como um número) são pas­sa­dos para as funções por val­or; o val­or é pas­sa­do para a função, mas se a função altera o val­or do parâmetro, esta mudança não reflete glob­al­mente ou na função chama­da.

Se você pas­sar um obje­to (ou seja, um  val­or não prim­i­ti­vo, tal como Array ou um obje­to definido por você) como um parâmetro e a função alter­ar as pro­priedades do obje­to, essa mudança é visív­el fora da função, con­forme mostra­do no exem­p­lo a seguir:

function minhaFuncao(objeto) {
  objeto.make = "Toyota";
}

var meucarro = {make: "Honda", model: "Accord", year: 1998};
var x, y;

x = meucarro.make;     // x recebe o valor "Honda"

minhaFuncao(meucarro);
y = meucarro.make;     // y recebe o valor "Toyota"
                    // (a propriedade make foi alterada pela função)

Expressão de função

Emb­o­ra a declar­ação de função aci­ma seja sintati­ca­mente uma declar­ação, funções tam­bém podem ser cri­adas por uma expressão de função. Tal função pode ser anôn­i­ma; ele não tem que ter um nome. Por exem­p­lo, a função square pode­ria ter sido defini­da como:

var square = function(numero) {return numero * numero}; 
var x = square(4) //x recebe o valor 16

No entan­to, um nome pode ser forneci­do com uma expressão de função e pode ser uti­liza­do no inte­ri­or da função para se referir a si mes­ma, ou em um debug­ger para iden­ti­ficar a função em stack traces:

var fatorial = function fac(n) {return n<2 ? 1 : n*fac(n-1)};

console.log(fatorial(3));

As expressões de função são con­ve­nientes ao pas­sar uma função como um argu­men­to para out­ra função. O exem­p­lo a seguir mostra uma função map sendo defini­da e, em segui­da, chama­da com uma função anôn­i­ma como seu primeiro parâmetro:

function map(f,a) {
  var result = []; // Cria um novo Array
  var i;
  for (i = 0; i != a.length; i++)
    result[i] = f(a[i]);
  return result;
}

O códi­go a seguir:

map(function(x) {return x * x * x}, [0, 1, 2, 5, 10]);

retor­na [0, 1, 8, 125, 1000].

Em JavaScript, uma função pode ser defini­da com base numa condição. Por exem­p­lo, a seguinte definição de função define minhaFuncao somente se num  é igual a 0:

var minhaFuncao;
if (num == 0){
  minhaFuncao = function(objeto) {
    objeto.make = "Toyota"
  }
}

Além de definir funções, você tam­bém pode usar o con­tru­tor Function para cri­ar funções a par­tir de uma stringem tem­po real, como no méto­do eval().

Um méto­do é uma função invo­ca­da por um obje­to. Leia mais sobre obje­tos e méto­dos em Tra­bal­han­do com Obje­tos.

Chamando funções

A definição de uma função não a exe­cu­ta. Definir a função é sim­ples­mente nomear a função e especi­ficar o que faz­er quan­do a função é chama­da. Chamar a função exe­cu­ta, real­mente, as ações especi­fi­cadas com os parâmet­ros indi­ca­dos. Por exem­p­lo, se você definir a função square, você pode chamá-la do seguinte modo: 

square(5);

A declar­ação ante­ri­or chama a função com o argu­men­to 5. A função exe­cu­ta as instruções e retor­na o val­or 25.

Funções devem estar no escopo quan­do são chamadas, mas a declar­ação de uma função pode ser alça­da para o topo (“hoist­ed”), como neste exem­p­lo:

console.log(square(5));
/* ... */
function square(n){return n*n}

O escopo de uma função é a função na qual ela é declar­a­da, ou todo o pro­gra­ma se ela é declar­a­da no nív­el supe­ri­or.

Nota: Isso fun­ciona ape­nas quan­do a definição da função usa a sin­taxe aci­ma (ex., function funcNome(){ }). O códi­go a seguir não vai fun­cionar.

console.log(square(5));
var square = function (n) {
  return n * n;
}

Os argu­men­tos de uma função não estão lim­i­ta­dos a strings e números. Você pode pas­sar obje­tos para uma função. A função show_props (definido em Tra­bal­han­do com Obje­tos) é um exem­p­lo de uma função que recebe um obje­to como um argu­men­to.

Um função pode chamar a si mes­ma. Por exem­p­lo, a função que cal­cu­la os fato­ri­ais recur­si­va­mente:

function fatorial(n){
  if ((n == 0) || (n == 1))
    return 1;
  else
    return (n * fatorial(n - 1));
}

Você pode­ria, então, cal­cu­lar os fato­ri­ais de um a cin­co:

var a, b, c, d, e;
a = fatorial(1); // a recebe o valor 1
b = fatorial(2); // b recebe o valor 2
c = fatorial(3); // c recebe o valor 6
d = fatorial(4); // d recebe o valor 24
e = fatorial(5); // e recebe o valor 120

Há out­ras maneiras de chamar funções. Muitas vezes há casos em que uma função pre­cisa ser chama­da dinami­ca­mente, ou o número de argu­men­tos de uma função varia, ou em que o con­tex­to da chama­da de função pre­cisa ser definido para um obje­to especí­fi­co deter­mi­na­do em tem­po de exe­cução. Acon­tece que as funções são, por si mes­mas, obje­tos, e ess­es obje­tos por sua vez têm méto­dos (veja obje­to Function). Um dess­es, o méto­do apply(), pode ser usa­do para atin­gir esse obje­ti­vo.

Escopo da função

As var­iáveis definidas no inte­ri­or de uma função não podem ser aces­sadas de nen­hum lugar fora da função, porque a var­iáv­el está defini­da ape­nas no escopo da função. No entan­to, uma função pode aces­sar todas var­iáveis e funções defini­da fora do escopo onde ela está defini­da. Em out­ras palavras, a função defini­da no escopo glob­al pode aces­sar todas as var­iáveis definidas no escopo glob­al. A função defini­da den­tro de out­ra função tam­bém pode aces­sar todas as var­iáveis definidas na função hos­pedeira e out­ras var­iáveis ao qual a função hos­pedeira tem aces­so.

// As seguintes variáveis são definidas no escopo global
var num1 = 20,
    num2 = 3,
    nome = "Chamahk";

// Esta função é definida no escopo global
function multiplica() {
  return num1 * num2;
}

multiplica(); // Retorna 60

// Um exemplo de função aninhada
function getScore () {
  var num1 = 2,
      num2 = 3;
  
  function add() {
    return nome + " scored " + (num1 + num2);
  }
  
  return add();
}

getScore(); // Retorna "Chamahk scored 5"

Escopo e a pilha de função

Recursão

Uma função pode referir-se e chamar a si própria. Há três maneiras de uma função referir-se a si mes­ma:

  1. o nome da função
  2. arguments.callee
  3. uma var­iáv­el no escopo que se ref­ere a função

Por exem­p­lo, con­sidere a seguinte definição de função:

var foo = function bar() {
   // declaracoes
};

Den­tro do cor­po da função, todos, a seguir, são equiv­a­lentes:

  1. bar()
  2. arguments.callee()
  3. foo()

Uma função que chama a si mes­ma é chama­da de função recur­si­va. Em alguns casos, a recur­sivi­dade é análo­ga a um laço. Ambos exe­cu­tam o códi­go várias vezes, e ambos neces­si­tam de uma condição (para evi­tar um laço infini­to, ou mel­hor, recursão infini­ta, neste caso). Por exem­p­lo,  o seguinte laço:

var x = 0;
while (x < 10) { // "x < 10" a condição do laço
   // faça coisas
   x++;
}

pode ser con­ver­tido em função recur­si­va e uma chama­da para a função:

function loop(x) {
   if (x >= 10) // "x >= 10" a condição de parada (equivalente a "!(x < 10)")
      return;
   // faça coisas
   loop(x + 1); // chamada recursiva
}
loop(0);

No entan­to, alguns algo­rit­mos não podem ser sim­ples laços iter­a­tivos. Por exem­p­lo, con­seguir todos os nós da estru­tu­ra de uma árvore (por exem­p­lo, o DOM) é mais fácil se feito recur­si­va­mente:

function walkTree(node) {
   if (node == null) // 
      return;
   // faça algo com o nó
   for (var i = 0; i < node.childNodes.length; i++) {
      walkTree(node.childNodes[i]);
   }
}

Em com­para­ção ao laço da função, cada chama­da recur­si­va real­iza out­ras chamadas recur­si­vas.

É pos­sív­el con­vert­er qual­quer algo­rit­mo recur­si­vo para um não recur­si­vo, mas muitas vezes a lóg­i­ca é muito mais com­plexa e exige o uso de pil­has. Na ver­dade a própria recursão usa pil­ha: a pil­ha de função.

O com­por­ta­men­to da pil­ha pode ser vista a seguir no exem­p­lo:

function foo(i) {
   if (i < 0)
      return;
   document.writeln('begin:' + i);
   foo(i - 1);
   document.writeln('end:' + i);
}
foo(3);

que pro­duz:

begin:3
begin:2
begin:1
begin:0
end:0
end:1
end:2
end:3

Funções aninhadas e closures

Você pode anin­har uma função den­tro de out­ra. A função anin­ha­da (inter­na) é acessív­el ape­nas para a função que a con­tém (exte­ri­or). Isso con­sti­tui tam­bém uma closure. Uma clo­sure é uma expressão (tipi­ca­mente uma função) que pode ter var­iáveis livres em con­jun­to com um ambi­ente que conec­ta estas var­iáveis (que “fecha” a expressão).

Uma vez que uma função anin­ha­da é uma clo­sure, isto sig­nifi­ca que uma função anin­ha­da pode “her­dar” os argu­men­tos e var­iáveis de sua função de con­tenção. Em out­ras palavras, a função inte­ri­or con­tém o escopo da função exte­ri­or.

Em resumo:

  • A função inter­na só pode ser aces­sa­da a par­tir de declar­ações em função exter­na.
  • A função inter­na for­ma uma clo­sure: a função  inter­na pode usar os argu­men­tos e var­iáveis da função exter­na, enquan­to a função exter­na não pode usar os argu­men­tos e var­iáveis da função inter­na.

O exem­p­lo a seguir mostra as funções anin­hadas:

function addSquares(a,b) {
   function square(x) {
      return x * x;
   }
   return square(a) + square(b);
}
a = addSquares(2,3); // retorna 13
b = addSquares(3,4); // retorna 25
c = addSquares(4,5); // retorna 41

Uma vez que a função inter­na for­ma uma clo­sure, você pode chamar a função exter­na e especi­ficar argu­men­tos para a função exter­na e inter­na:

function fora(x) {
   function dentro(y) {
      return x + y;
   }
   return dentro;
}
fn_inside = fora(3); // Pense nisso como: Receba uma função que adicionará 3 ao que quer que você repasse para ela
result = fn_inside(5); // retorna 8

result1 = fora(3)(5); // retorna 8

Preservação  de variáveis

Observe como x é preser­va­do quan­do dentro é retor­na­do. Uma clo­sure deve preser­var os argu­men­tos e var­iáveis em todos os esco­pos que ela ref­er­en­cia. Uma vez que cada chama­da fornece poten­cial­mente argu­men­tos difer­entes, uma nova clo­sure é cri­a­da para cada chama­da de fora. A memória só poderá ser lib­er­a­da quan­do o dentro retor­na­do já não é mais acessív­el.

Isso não é difer­ente de armazenar refer­ên­cias em out­ros obje­tos, mas muitas vezes é menos óbvio, porque um não define dire­ta­mente as refer­ên­cias e não pode inspe­cioná-las.

Múltiplas funções aninhadas

Funções podem ter múlti­p­lo anin­hamen­to, por exem­p­lo, a função (A) con­tém a função (B) que con­tém a função ©. Tan­to as funções B e C for­mam uma clo­sure, então B pode aces­sar A, e C pode aces­sar B. Além dis­so, uma vez que C pode aces­sar B que pode aces­sar A, C tam­bém pode aces­sar A. Assim, a clo­sure pode con­ter vários esco­pos; eles recur­si­va­mente con­tém o escopo das funções que os con­tém. Isso é chama­do encadeamento de escopo. (Porque isso é chama­do de “encadea­men­to”, será expli­ca­do mais tarde).

Con­sidere o seguinte exem­p­lo:

function A(x) {
   function B(y) {
      function C(z) {
         alert(x + y + z);
      }
      C(3);
   }
   B(2);
}
A(1); // Exibe um alerta com o valor 6 (1 + 2 + 3)

Neste exem­p­lo, C aces­sa y do B e x do A. Isso pode ser feito porque:

  1. B for­ma uma clo­sure incluin­do A, isto é, B pode aces­sar argu­men­tos e var­iáveis de A.
  2. C for­ma uma clo­sure incluin­do B.
  3.  Dev­i­do a clo­sure B inclui A, a clo­sure C inclui AC pode aces­sar tan­to argu­men­tos e var­iáveis de B como de A. Em out­ras palavras, C encadeia o escopo de B e A, nes­ta ordem.

O inver­so, no entan­to, não é ver­dadeiro. A não pode aces­sar C, porque A não pode aces­sar qual­quer argu­men­to ou var­iáv­el de B. Assim, C é pri­va­do somente a B.

Conflitos de nome

Quan­do dois argu­men­tos ou var­iáveis nos esco­pos da clo­sure tem o mes­mo nome, há um con­fli­to de nome. Mas esco­pos inter­nos tem pri­or­i­dade, por isso o escopo mais inter­no tem a maior pri­or­i­dade, enquan­to que o escopo mais exter­no tem a menor. Esta é a cadeia de escopo. O primeiro da cadeia é o escopo mais inter­no, e o últi­mo é o escopo mais exter­no. Con­sidere o seguinte:

function fora() {
   var x = 10;
   function dentro(x) {
      return x;
   }
   return dentro;
}
result = fora()(20); // retorna 20 em vez de 10

O  con­fli­to de nome acon­tece na declar­ação return x e está entre o parâmetro x de dentro e a var­iáv­el x de fora. A cadeia de escopo aqui é {dentrofora, obje­to glob­al}. Por isso o x de dentro tem pre­cedên­cia sobre o x de fora, e 20 (x de dentro) é retor­na­do em vez de 10 (x de fora).

Closures

Clo­sures são um dos recur­sos mais poderosos de JavaScript. JavaScript per­mite o anin­hamen­to de funções e garante aces­so com­ple­to à função inter­na a todas as var­iáveis e funções definidas den­tro da função exter­na (e todas as out­ras var­iáveis e funções que a função exter­na tem aces­so). No entan­to, a função exter­na não tem aces­so às var­iáveis e funções definidas den­tro da função inter­na. Isto pro­por­ciona uma espé­cie de segu­rança para as var­iáveis da função inter­na. Além dis­so, uma vez  que a função inter­na tem aces­so ao escopo da função exter­na, as var­iáveis e funções definidas na função exter­na vão durar na memória mais do que a própria função exter­na, isto se a função inter­na per­manecer na memória mais tem­po do que a função exter­na. Uma clo­sure é cri­a­da quan­do a função inter­na é de algu­ma for­ma disponi­bi­liza­da para qual­quer escopo fora da função exter­na.

var pet = function(nome) {          // A função externa define uma variável "nome"
      var getNome = function() {
        return nome;                // A função interna tem acesso à variável "nome"  da função externa
      }

      return getNome;               // Retorna a função interna, expondo-a assim para escopos externos
    },
    myPet = pet("Vivie");
    
myPet();                            // Retorna "Vivie"

Ela pode ser  mais com­plexa que o códi­go aci­ma. Um obje­to con­tendo méto­dos para manip­u­lar as var­iáveis da função exter­na pode ser devolvi­da.

var criarPet = function(nome) {
  var sex;
  
  return {
    setNome: function(newNome) {
      nome = newNome;
    },
    
    getNome: function() {
      return nome;
    },
    
    getSex: function() {
      return sex;
    },
    
    setSex: function(newSex) {
      if(typeof newSex == "string" && (newSex.toLowerCase() == "macho" || newSex.toLowerCase() == "fêmea")) {
        sex = newSex;
      }
    }
  }
}

var pet = criarPet("Vivie");
pet.getNome();                  // Vivie

pet.setNome("Oliver");
pet.setSex("macho");
pet.getSex();                   // macho
pet.getNome();                  // Oliver

Nos códi­gos aci­ma, a var­iáv­el nome da função exter­na é acessív­el para as funções inter­nas, e não há nen­hu­ma out­ra maneira para aces­sar as var­iáveis inter­nas, exce­to pelas funções inter­nas. As var­iáveis inter­nas da função inter­na atu­am como armazena­men­to seguro para as funções inter­nas. Elas armazenam “per­sis­tentes”, mas seguros, os dados com os quais as funções inter­nas irão tra­bal­har. As funções não tem  que ser atribuí­das a uma var­iáv­el, ou ter um nome.

var getCode = (function(){
  var secureCode = "0]Eal(eh&2";    // Um código que não queremos que pessoas de fora sejam capazes de modificar
  
  return function () {
    return secureCode;
  };
})();

getCode();    // Retorna o secureCode

Há, no entan­to, uma série de armadil­has que se deve ter cuida­do ao usar clo­sures. Se uma função fecha­da define uma var­iáv­el com o mes­mo nome de uma var­iáv­el em um escopo exter­no, não há nen­hu­ma maneira de se referir para a var­iáv­el em um escopo exter­no nova­mente.

var createPet = function(nome) {  // Função externa define uma variável chamada "nome"
  return {
    setNome: function(nome) {    // Função fechada define uma variável chamada "nome"
      nome = nome;               // ??? Como podemos acessar o "nome" definido pela função externa ???
    }
  }
}

A palavra reser­va­da this é muito com­pli­ca­da em clo­sures.  Elas têm de ser usadas com muito cuida­do, como ao que this se ref­ere depende com­ple­ta­mente de onde a função foi chama­da, ao invés de onde ela foi defini­da.

Usando objeto de argumentos

Os argu­men­tos de uma função são man­ti­dos em um obje­to do tipo array. Den­tro de uma função, você pode endereçar os argu­men­tos pas­sa­dos para ele con­forme: 

arguments[i]

onde i é um número ordi­nal do argu­men­to, começan­do com zero. Então, o primeiro argu­men­to pas­sa­do para a função seria arguments[0]. O número total de argu­men­tos é indi­ca­do por arguments.length.

Usan­do o obje­to arguments, você pode chamar a função com mais argu­men­tos do que o for­mal­mente declar­a­do. Isso muitas vezes é útil se você não sabe de antemão quan­tos argu­men­tos serão pas­sa­dos para a função. Você pode usar arguments.length para deter­mi­nar a quan­ti­dade de argu­men­tos pas­sa­dos para a função, e então aces­sar cada argu­men­to usan­do o obje­to arguments.

Por exem­p­lo, con­sidere uma função que con­cate­na várias strings. O argu­men­to for­mal para a função é uma string que especi­fi­ca os car­ac­teres que sep­a­ram os itens para con­cate­nar.  A função defini­da como segue:

function myConcat(separador) {
   var result = "", // inicializa a lista
       i;
   // itera por meio de argumentos
   for (i = 1; i < arguments.length; i++) {
      result += arguments[i] + separador;
   }
   return result;
}

Você pode pas­sar qual­quer quan­ti­dade de argu­men­tos para esta função, e ela con­cate­na cada argu­men­to na string “list”:

// retorna "red, orange, blue, "
myConcat(", ", "red", "orange", "blue");

// retorna "elephant; giraffe; lion; cheetah; "
myConcat("; ", "elephant", "giraffe", "lion", "cheetah");

// retorna "sage. basil. oregano. pepper. parsley. "
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");

Nota: A var­iáv­el arguments é “como um array”, mas não é um array. Ela é como um array pois pos­sui um índice numer­a­do e a pro­priedade length. No entan­to, não pos­sui todos os méto­dos de manip­u­lação de array. 

Veja obje­to Function na refer­ên­cia do JavaScript para maiores infor­mações.

Parâmetros de função

Começan­do com ECMAScript 6, há dois tipos novos de parâmet­ros: parâmet­ros padrão e parâmet­ros rest.

Parâmetros padrão

Em JavaScript, parâmet­ros padrões de funções são undefined. No entan­to, em algu­mas situ­ações pode ser útil definir um val­or padrão difer­ente. Isto é onde os parâmet­ros padrão podem aju­dar.

No pas­sa­do, a estraté­gia ger­al para definir padrões era tes­tar os val­ores de parâmetro no cor­po da função e atribuir um val­or se eles fos­sem undefined. Se, no exem­p­lo a seguir, nen­hum val­or é forneci­do para b na chama­da, seu val­or seria undefined ao avaliar a*b e a chama­da para multiplicar retornar­ia NaN. No entan­to, isso é pego com a segun­da lin­ha neste exem­p­lo:

function multiplicar(a, b) {
  b = typeof b !== 'undefined' ?  b : 1;

  return a*b;
}

multiplicar(5); // 5

Com parâmet­ros padrão, a ver­i­fi­cação no cor­po da função não é mais necessária. Ago­ra você pode sim­ples­mente colo­car 1 como val­or padrão para b no cam­po de declar­ação de parâmet­ros:

function multiplicar(a, b = 1) {
  return a*b;
}

multiplicar(5); // 5

Parâmetros rest

A sin­taxe de parâmetro rest per­mite rep­re­sen­tar um número indefinido de argu­men­tos como um array. No exem­p­lo, usamos parâmet­ros rest para cole­tar argu­men­tos do segun­do argu­men­to ao últi­mo. Então os mul­ti­pli­camos pelo primeiro argu­men­to. Neste exem­p­lo é usa­do uma função seta, que será intro­duzi­da na próx­i­ma seção.

function multiplicar(multiplicador, ...args) {
  return args.map(x => multiplicador * x);
}

var arr = multiplicar(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]

Funções de seta

Uma expressão função de seta (ante­ri­or­mente con­heci­da como função de seta gor­da) tem uma sin­taxe peque­na em com­para­ção com a expressão de função e lex­i­cal­mente vin­cu­la o val­or this. Funções de seta são sem­pre anôn­i­mas. Con­sulte tam­bém no blog hacks.mozilla.org no post: “ES6 In Depth: Arrow func­tions”.

Dois fatores influ­en­cia­ram a intro­dução de funções de seta: funções mais cur­tas e o léx­i­co this.

Funções curtas

Em alguns padrões fun­cionais, funções cur­tas são bem-vin­das. Com­pare:

var a = [
  "Hydrogen",
  "Helium",
  "Lithium",
  "Beryl­lium"
];

var a2 = a.map(function(s){ return s.length });

var a3 = a.map( s => s.length );

Léxico this

Até as funções de seta, cada nova função definia seu próprio val­or this (um novo obje­to no caso de um con­stru­tor, indefinido em chamadas de função no modo estri­to, o obje­to de con­tex­to se a função é chama­da como um “méto­do de obje­to”, etc.). Isso pode ser irri­tante com um esti­lo de pro­gra­mação ori­en­ta­da a obje­tos.

function Pessoa() {      // O construtor Pessoa() define 'this' como sendo ele.   
    this.idade = 0; 
    setInterval(function crescer() {    // No modo não estrito, a função crescer define 'this'
            // como o objeto global, o que é diferente do 'this'
            // definido pelo construtor Pessoa().
            this.idade++; 
     }, 1000); 
} 
var p = new Pessoa();

No ECMAScript 3/5, este prob­le­ma foi resolvi­do atribuin­do o val­or em this a uma var­iáv­el que pode­ria ser fecha­da.

function Pessoa() {
  var self = this; // Alguns preferem 'that' em vez de 'self'. 
                   // Escolha um e seja consistente.
  self.idade = 0;

  setInterval(function crescer() {
    // A chamada de retorno refere-se à variável 'self' na qual
    // o valor é o objeto esperado.
    self.idade++;
  }, 1000);
}

Como alter­na­ti­va, uma função vin­cu­la­da pode­ria ser cri­a­da para que o val­or da pro­priedade this seja pas­sa­do para a função crescer().

Funções de seta cap­turam o val­or this do con­tex­to delim­i­ta­do, então o códi­go a seguir fun­ciona con­forme o esper­a­do.

function Pessoa(){
  this.idade = 0;

  setInterval(() => {
    this.idade++; // propriedade |this|refere ao objeto pessoa
  }, 1000);
}

var p = new Pessoa();

Funções pré-definidas

JavaScript tem várias funções pré-definidas:eval()

O méto­do eval() avalia códi­go JavaScript rep­re­sen­ta­do como uma string.uneval()

O méto­do uneval() cria uma rep­re­sen­tação de string do códi­go-fonte de um  Object.isFinite()

A função glob­al isFinite() deter­mi­na se o val­or pas­sa­do é um número fini­to. Se necessário, o parâmetro é primeiro con­ver­tido para um número.isNaN()

A função isNaN() deter­mi­na se um val­or é NaN ou não. Nota: coerção den­tro da função isNaN tem regras inter­es­santes; você pode, alter­na­ti­va­mente, quer­er usar Number.isNaN(), como definido no ECMAScript 6,  ou você pode usar typeof para deter­mi­nar se o val­or não é um número.parseFloat()

A função parseFloat() anal­isa um argu­men­to do tipo string e retor­na um número de pon­to flu­tu­ante.parseInt()

A função parseInt() anal­isa um argu­men­to do tipo string e retor­na um inteiro da base especi­fi­ca­da (base do sis­tema numéri­co).decodeURI()

A função decodeURI() decod­i­fi­ca uma Uni­form Resource Iden­ti­fi­er (URI) cri­a­da ante­ri­or­mente por encodeURI ou por uma roti­na sim­i­lar.decodeURIComponent()

O méto­do decodeURIComponent() decod­i­fi­ca um com­po­nente Uni­form Resource Iden­ti­fi­er (URI) cri­a­do ante­ri­or­mente por encodeURIComponent ou por uma roti­na sim­i­lar.encodeURI()

O méto­do encodeURI() cod­i­fi­ca um Uni­form Resource Iden­ti­fi­er (URI), sub­sti­tuin­do cada ocor­rên­cia de deter­mi­na­dos car­ac­teres por um, dois, três, ou qua­tro sequên­cias de escape que rep­re­sen­ta a cod­i­fi­cação UTF‑8 do car­ac­ter (só serão qua­tro sequên­cias de escape para car­ac­teres com­pos­tos de dois car­ac­teres “sub­sti­tu­tos”).encodeURIComponent()

O méto­do encodeURIComponent() cod­i­fi­ca um com­po­nente Uni­form Resource Iden­ti­fi­er (URI), sub­sti­tuin­do cada ocor­rên­cia de deter­mi­na­dos car­ac­teres por um, dois, três, ou qua­tro sequên­cias de escape que rep­re­sen­ta a cod­i­fi­cação UTF‑8 do car­ac­ter (só serão qua­tro sequên­cias de escape para car­ac­teres com­pos­tos de dois car­ac­teres “sub­sti­tu­tos”).escape()

O méto­do obso­le­to escape() cal­cu­la uma nova string na qual cer­tos car­ac­teres foram sub­sti­tuí­dos por uma sequên­cia de escape hexa­dec­i­mal. Use encodeURI ou encodeURIComponent em vez dis­so.unescape()

O méto­do obso­le­to unescape() cal­cu­la uma nova string na qual sequên­cias de escape hexa­dec­i­mais são sub­sti­tuí­das pelo car­ac­tere que ela rep­re­sen­ta. As sequên­cias de escape podem ser intro­duzi­das por uma função como escape. Por unescape() estar obso­le­to, use decodeURI() ou decodeURIComponent ao invés dele.

Operadores

O JavaScript pos­sui os tipos de oper­adores a seguir. Esta seção descreve os oper­adores e con­tém infor­mações sobre pre­cedên­cia de oper­adores.

  • Oper­adores de atribuição
  • Oper­adores de com­para­ção
  • Oper­adores arit­méti­cos
  • Oper­adores bit a bit
  • Oper­adores lógi­cos
  • Oper­adores de string
  • Oper­ador condi­cional (ternário)
  • Oper­ador vír­gu­la
  • Oper­adores unário
  • Oper­adores rela­cionais

O JavaScript pos­sui tan­to oper­adores binários quan­to unários e um oper­ador ternário, o oper­ador condi­cional. Um oper­ador binário exige dois operan­dos, um antes do oper­ador e out­ro depois:

operando1 operador operando2

Por exem­p­lo, 3+4 ou x*y.

Um oper­ador unário exige um úni­co operan­do, seja antes ou depois do oper­ador:

operador operando

ou

operando operador

Por exem­p­lo, x++ ou ++x.

Operadores de atribuição

Um oper­ador de atribuição atribui um val­or ao operan­do à sua esquer­da basea­do no val­or do operan­do à dire­i­ta. O oper­ador de atribuição bási­co é o igual (=), que atribui o val­or do operan­do à dire­i­ta ao operan­do à esquer­da. Isto é, x = y atribui o val­or de y a x.

Os out­ros oper­adores de atribuição são encur­ta­men­tos de oper­adores padrão, como mostra­do na tabela a seguir.

NomeOper­ador encur­ta­doSig­nifi­ca­do
Atribuiçãox = yx = y
Atribuição de adiçãox += yx = x + y
Atribuição de sub­traçãox -= yx = x - y
Atribuição de mul­ti­pli­caçãox *= yx = x * y
Atribuição de divisãox /= yx = x / y
Atribuição de restox %= yx = x % y
Atribuição expo­nen­cialx **= yx = x ** y
Atribuição bit-a-bit por deslo­ca­men­to á esquer­dax <<= yx = x << y
Atribuição bit-a-bit por deslo­ca­men­to á dire­i­tax >>= yx = x >> y
Atribuiçãode bit-a-bit deslo­ca­men­to á dire­i­ta não assi­na­dox >>>= yx = x >>> y
Atribuição AND bit-a-bitx &= yx = x & y
Atribuição XOR bit-a-bitx ^= yx = x ^ y
Atribuição OR bit-a-bitx |= yx = x | y

Operadores de comparação

Um oper­ador de com­para­ção com­para seus operan­dos e retor­na um val­or lógi­co basea­do em se a com­para­ção é ver­dadeira. Os operan­dos podem ser numéri­cos, strings, lógi­cos ou obje­tos. Strings são com­para­das com base em orde­nação lex­o­grá­fi­ca uti­lizan­do val­ores Uni­code. Na maio­r­ia dos casos, se dois operan­dos não são do mes­mo tipo, o JavaScript ten­ta con­vertê-los para um tipo apro­pri­a­do. Isto geral­mente resul­ta na real­iza­ção de uma com­para­ção numéri­ca. As úni­cas exceções a esta regra são os oper­adores === e o !==, que real­izam com­para­ções de igual­dade e desigual­dade “estri­tas”. Estes oper­adores não ten­tam con­vert­er os operan­dos em tipos com­patíveis antes de ver­i­ficar a igual­dade. A tabela a seguir descreve os oper­adores de com­para­ção levan­do em con­ta o seguinte códi­go:

var var1 = 3;
var var2 = 4;
Oper­adorDescriçãoExem­p­los que retor­nam ver­dadeiro
Igual (==)Retor­na ver­dadeiro caso os operan­dos sejam iguais.3 == var1"3" == var13 == '3'
Não igual (!=)Retor­na ver­dadeiro caso os operan­dos não sejam iguais.var1 != 4
var2 != "3"
Estri­ta­mente igual (===)Retor­na ver­dadeiro caso os operan­dos sejam iguais e do mes­mo tipo. Veja tam­bém Object.is e igual­dade em JS.3 === var1
Estri­ta­mente não igual (!==)Retor­na ver­dadeiro caso os operan­dos não sejam iguais e/ou não sejam do mes­mo tipo.var1 !== "3"
3 !== '3'
Maior que (>)Retor­na ver­dadeiro caso o operan­do da esquer­da seja maior que o da dire­i­ta.var2 > var1
"12" > 2
Maior que ou igual (>=)Retor­na ver­dadeiro caso o operan­do da esquer­da seja maior ou igual ao da dire­i­ta.var2 >= var1
var1 >= 3
Menor que (<)Retor­na ver­dadeiro caso o operan­do da esquer­da seja menor que o da dire­i­ta.var1 < var2
"12" < "2"
Menor que ou igual (<=)Retor­na ver­dadeiro caso o operan­do da esquer­da seja menor ou igual ao da dire­i­ta.var1 <= var2
var2 <= 5

Nota: (=>) não é um oper­ador, mas a notação para função de seta

Operadores aritméticos

Oper­adores arit­méti­cos tomam val­ores numéri­cos (sejam lit­erais ou var­iáveis) como seus operan­dos e retor­nam um úni­co val­or númeri­co. Os oper­adores arit­méti­cos padrão são os de soma (+), sub­tração (-), mul­ti­pli­cação (*) e divisão (/). Estes oper­adores tra­bal­ham da mes­ma for­ma como na maio­r­ia das lin­gua­gens de pro­gra­mação quan­do uti­liza­dos com números de pon­to flu­tu­ante (em par­tic­u­lar, repare que divisão por zero pro­duz um NaN). Por exem­p­lo:

console.log(1 / 2); /* imprime 0.5 */
console.log(1 / 2 == 1.0 / 2.0); /* isto também é verdadeiro */

Em com­ple­men­to às oper­ações arit­méti­cas padrões (+, -, * /), o JavaScript disponi­bi­liza os oper­adores arit­méti­cos lis­ta­dos na tabela a seguir.

Oper­adorDescriçãoExem­p­lo
Módu­lo (%)Oper­ador binário. Retor­na o inteiro restante da divisão dos dois operan­dos.12 % 5 retor­na 2.
Incre­men­to (++)Oper­ador unário. Adi­ciona um ao seu operan­do. Se usa­do como oper­ador pre­fix­a­do (++x), retor­na o val­or de seu operan­do após a adição. Se usa­do como oper­ador pós­fix­a­do (x++), retor­na o val­or de seu operan­do antes da adição.Se x é 3, então ++x define x como 4 e retor­na 4, enquan­to x++ retor­na 3 e, somente então, define x como 4.
Decre­men­to (–)Oper­ador unário. Sub­trai um de seu operan­do. O val­or de retorno é anál­o­go àquele do oper­ador de incre­men­to.Se x é 3, então --x define x como 2 e retor­na 2, enquan­to x-- retor­na 3 e, somente então, define x como 2.
Negação (-)Oper­ador unário. Retor­na a negação de seu operan­do.Se x é 3, então -x retor­na ‑3.
Adição (+)Oper­ador unário. Ten­ta con­vert­er o operan­do em um número, sem­pre que pos­sív­el.+“3” retor­na 3.+true retor­na 1.
Oper­ador de expo­nen­ci­ação (**) Cal­cu­la a base ele­va­da á potên­cia do expoente, que é, baseexpoente2 ** 3 retor­na 8.10 ** ‑1 retor­na 0.1

Operadores bit a bit

Oper­adores bit a bit tratam seus operan­dos como um con­jun­to de 32 bits (zeros e uns), em vez de tratá-los como números dec­i­mais, hexa­dec­i­mais ou octais. Por exem­p­lo, o número dec­i­mal nove pos­sui uma rep­re­sen­tação binária 1001. Oper­adores bit a bit real­izam suas oper­ações nes­tas rep­re­sen­tações, mas retor­nam val­ores numéri­cos padrões do JavaScript.

A tabela a seguir resume os oper­adores bit a bit do JavaScript.

Oper­adorExpressãoDescrição
ANDa & bRetor­na um 1 para cada posição em que os bits da posição cor­re­spon­dente de ambos operan­dos sejam uns.
ORa | bRetor­na um 0 para cada posição em que os bits da posição cor­re­spon­dente de  ambos os operan­dos sejam zeros.
XORa ^ bRetor­na um 0 para cada posição em que os bits da posição cor­re­spon­dente são os mes­mos.

[Retor­na um 1 para cada posição em que os bits da posição cor­re­spon­dente sejam difer­entes.]
NOT~ aInverte os bits do operan­do.
Deslo­ca­men­to à esquer­daa << bDeslo­ca a em rep­re­sen­tação binária b bits à esquer­da, preenchen­do com zeros à dire­i­ta.
Deslo­ca­men­to à dire­i­ta com propa­gação de sinala >> bDeslo­ca a em rep­re­sen­tação binária b bits à dire­i­ta, descar­tan­do bits exce­dentes.
Deslo­ca­men­to à dire­i­ta com preenchi­men­to zeroa >>> bDeslo­ca a em rep­re­sen­tação binária b bits à dire­i­ta, descar­tan­do bits exce­dentes e preenchen­do com zeros à esquer­da.

Operadores bit a bit lógicos

Con­ceitual­mente, os oper­adores bit a bit lógi­cos fun­cionam da seguinte maneira:

  • Os operan­dos são con­ver­tidos em inteiros de 32 bits e expres­sos como uma série de bits (zeros e uns). Números com rep­re­sen­tação maior que 32 bits terão seus bits trun­ca­dos. Por exem­p­lo, o seguinte inteiro tem rep­re­sen­tação binária maior que 32 bits será con­ver­tido em um inteiro de 32 bits.
Antes: 11100110111110100000000000000110000000000001
Depois:            10100000000000000110000000000001
  • Cada bit do primeiro operan­do é parea­do com o bit cor­re­spon­dente do segun­do operan­do: primeiro bit com primeiro bit, segun­do bit com segun­do bit e assim por diante.
  • O oper­ador é apli­ca­do a cada par de bits e o resul­ta­do é con­struí­do bit a bit.

Por exem­p­lo, a rep­re­sen­tação binária de nove é 1001 e a rep­re­sen­tação binária de quinze é 1111. Des­ta for­ma, quan­do oper­adores bit a bit são apli­ca­dos a estes val­ores, os resul­ta­dos são como se segue:

ExpressãoResul­ta­doDescrição binária
15 & 991111 & 1001 = 1001
15 | 9151111 | 1001 = 1111
15 ^ 961111 ^ 1001 = 0110
~15-16~00000000...00001111 = 11111111...11110000
~9-10~00000000...00001001 = 11111111...11110110

Nota: No quadro aci­ma perce­ba que todos os 32 bits são inver­tidos quan­do usa-se o oper­ador bit a bit NOT, e que os bits mais sig­ni­fica­tivos (extrema esquer­da) são definidos com 1 que rep­re­sen­tam val­ores neg­a­tivos (rep­re­sen­tação com­ple­men­to de dois).

Operadores de deslocamento bit a bit

Os oper­adores de deslo­ca­men­to bit a bit pos­sui dois operan­dos: o primeiro é uma quan­ti­dade a ser deslo­ca­da e o segun­do especi­fi­ca o número de posições binárias as quais o primeiro operan­do dev­erá ser deslo­ca­do. A direção da oper­ação de deslo­ca­men­to é con­tral­a­da pelo oper­ador uti­liza­do.

Oper­adores de deslo­ca­men­to con­vertem seus operan­dos em inteiros de 32 bits e retor­nam um resul­ta­do do tipo do operan­do à esquer­da.

Os oper­adores de deslo­ca­men­to são lis­ta­dos na tabela a seguir.

Oper­adorDescriçãoExem­p­lo
Deslocamento à esquerda (<<)Este oper­ador deslo­ca o primeiro operan­do pelo número especi­fi­ca­do de bits à esquer­da. Bits exce­dentes deslo­ca­dos para fora do lim­ite à esquer­da são descar­ta­dos. Bits zero são inseri­dos à dire­i­ta.9<<2 pro­duz 36 porque 1001 deslo­ca­do 2 bits à esquer­da se tor­na 100100, que é 36.
Deslo­ca­men­to à dire­i­ta com propa­gação de sinal
(>>)
Este oper­ador deslo­ca o primeiro operan­do pelo número especi­fi­ca­do de bits à dire­i­ta. Bits exce­dentes deslo­ca­dos para fora do lim­ite à dire­i­ta são descar­ta­dos. Cópias dos bits mais à esquer­da são deslo­cadas a par­tir da esquer­da.9>>2 pro­duz 2 porque 1001 deslo­ca­do 2 bits à dire­i­ta se tor­na 10, que é 2. De for­ma sim­i­lar, -9>>2 pro­duz ‑3 porque o sinal é preser­va­do.
Deslo­ca­men­to à dire­i­ta com preenchi­men­to zero
(>>>)
Este oper­ador deslo­ca o primeiro operan­do pelo número especi­fi­ca­do de bits à dire­i­ta. Bits exce­dentes deslo­ca­dos para fora do lim­ite à dire­i­ta são descar­ta­dos. Bits zero são inseri­dos à esquer­da.19>>>2 pro­duz 4 porque 10011 deslo­ca­do 2 bits à dire­i­ta se tor­na 100, que é 4. Para números não neg­a­tivos o deslo­ca­men­to à dire­i­ta com propa­gação de sinal e o deslo­ca­men­to à dire­i­ta com preenchi­men­to zero pro­duzem o mes­mo resul­ta­do.

Operadores lógicos

Oper­adores lógi­cos são uti­liza­dos tipi­ca­mente com val­ores booleanos (lógi­cos); neste caso, retor­nam um val­or booleano. Entre­tan­to, os oper­adores && e || na ver­dade retor­nam o val­or de um dos operan­dos especi­fi­ca­dos, de for­ma que se ess­es oper­adores forem uti­liza­dos com val­ores não-booleanos, eles pos­sam retornar um val­or não-booleano. Os oper­adores lógi­cos são descritos na seguinte tabela.

Oper­adorUti­liza­çãoDescrição
AND lógico (&&)expr1 && expr2(E lógi­co) — Retor­na expr1 caso pos­sa ser con­ver­tido para fal­so; senão, retor­na expr2. Assim, quan­do uti­liza­do com val­ores booleanos, && retor­na ver­dadeiro caso ambos operan­dos sejam ver­dadeiros; caso con­trário, retor­na fal­so.
OU lógico (||)expr1 || expr2(OU lógi­co) —  Retor­na expr1 caso pos­sa ser con­ver­tido para ver­dadeiro; senão, retor­na expr2. Assim, quan­do uti­liza­do com val­ores booleanos, || retor­na ver­dadeiro caso ambos os operan­dos sejam ver­dadeiro; se ambos forem fal­sos, retor­na fal­so.
NOT lógico (!)!expr(Negação lóg­i­ca) Retor­na fal­so caso o úni­co operan­do pos­sa ser con­ver­tido para ver­dadeiro; senão, retor­na ver­dadeiro.

Exem­p­los de expressões que podem ser con­ver­tidas para fal­so são aque­las que são avali­a­dos como nulo, 0, string vazia (“”) ou undefined.

O códi­go a seguir mostra exem­p­los do oper­ador && (E lógi­co).

var a1 =  true && true;     // t && t retorna true
var a2 =  true && false;    // t && f retorna false
var a3 = false && true;     // f && t retorna false
var a4 = false && (3 == 4); // f && f retorna false
var a5 = "Gato" && "Cão";   // t && t retorna Cão
var a6 = false && "Gato";   // f && t retorna false
var a7 = "Gato" && false;   // t && f retorna false

O códi­go a seguir mostra exem­p­los do oper­ador || (OU lógi­co).

var o1 =  true || true;     // t || t retorna true
var o2 = false || true;     // f || t retorna true
var o3 =  true || false;    // t || f retorna true
var o4 = false || (3 == 4); // f || f retorna false
var o5 = "Gato" || "Cão";   // t || t retorna Gato
var o6 = false || "Gato";   // f || t retorna Gato
var o7 = "Gato" || false;   // t || f retorna Gato

O códi­go a seguir mostra exem­p­los do oper­ador ! (negação lóg­i­ca).

var n1 = !true;   // !t retorna false
var n2 = !false;  // !f retorna true
var n3 = !"Gato"; // !t retorna false

Avaliação de curto-circuito

Como expressões lóg­i­cas são avali­adas da esquer­da para a dire­i­ta, elas são tes­tadas como pos­síveis avali­ações de “cur­to-cir­cuito” uti­lizan­do as seguintes regras:

  • false && qual­quer­coisa é avali­a­do em cur­to-cir­cuito como fal­so.
  • true || qual­quer­coisa é avali­a­do em cur­to-cir­cuito como ver­dadeiro.

As regras de lóg­i­ca garan­tem que estas avali­ações este­jam sem­pre cor­re­tas. Repare que a parte qual­quer­coisa das expressões aci­ma não é avali­a­da, de for­ma que qual­quer efeito colat­er­al de fazê-lo não pro­duz efeito algum.

Operadores de string

Além dos oper­adores de com­para­ção, que podem ser uti­liza­dos em val­ores string, o oper­ador de con­cate­nação (+) con­cate­na dois val­ores string, retor­nan­do out­ra string que é a união dos dois operan­dos.

Por exem­p­lo,

 console.log("minha " + "string"); // exibe a string "minha string".

O oper­ador de atribuição encur­ta­do += tam­bém pode ser uti­liza­do para con­cate­nar strings.

Por exem­p­lo,

var minhaString = "alfa";
minhaString += "beto"; // É avaliada como "alfabeto" e atribui este valor a minhastring.

Operador condicional (ternário)

O oper­ador condi­cional é o úni­co oper­ador JavaScript que uti­liza três operan­dos. O oper­ador pode ter um de dois val­ores basea­d­os em uma condição. A sin­taxe é:

condicao ? valor1 : valor2

Se condicao for ver­dadeira, o oper­ador terá o val­or de valor1. Caso con­trário, terá o val­or de valor2. Você pode uti­lizar o oper­ador condi­cional em qual­quer lugar onde uti­lizaria um oper­ador padrão.

Por exem­p­lo,

var status = (idade >= 18) ? "adulto" : "menor de idade";

Esta declar­ação atribui o val­or “adul­to” à var­iáv­el status caso idade seja dezoito ou mais. Caso con­trário, atribui o val­or “menor de idade”.

Operador vírgula

O oper­ador vír­gu­la (,) sim­ples­mente avalia ambos de seus operan­dos e retor­na o val­or do segun­do. Este oper­ador é uti­liza­do pri­mari­a­mente den­tro de um laço for para per­mi­tir que mul­ti­plas var­iáveis sejam atu­al­izadas cada vez através do laço.

Por exem­p­lo, se a é uma matriz bidi­men­sion­al com 10 ele­men­tos em um lado, o códi­go a seguir uti­liza o oper­ador vír­gu­la para incre­men­tar duas var­iáveis de uma só vez. O códi­go imprime os val­ores dos ele­men­tos diag­o­nais da matriz:

for (var i = 0, j = 9; i <= 9; i++, j--)
  console.log("a[" + i + "][" + j + "]= " + a[i][j]);

Operadores unário

Um oper­ador unário é uma oper­ação com ape­nas um operan­do.

delete

O oper­ador delete apa­ga um obje­to, uma pro­priedade de um obje­to ou um ele­men­to no índice especi­fi­ca­do de uma matriz. A sin­taxe é:

delete nomeObjeto;
delete nomeObjeto.propriedade;
delete nomeObjeto[indice];
delete propriedade; // válido apenas dentro de uma declaração with

onde nomeObjeto é o nome de um obje­to, propriedade é uma pro­priedade exis­tente e indice é um inteiro que rep­re­sen­ta a local­iza­ção de um ele­men­to em uma matriz.

A quar­ta for­ma é per­mi­ti­da somente den­tro de uma declar­ação with para apa­gar uma pro­priedade de um obje­to.

Você pode uti­lizar o oper­ador delete para apa­gar var­iáveis declar­adas implici­ta­mente mas não aque­las declar­adas com var.

Se o oper­ador delete for bem-suce­di­do, ele define a pro­priedade ou ele­men­to para undefined. O oper­ador delete retor­na ver­dadeiro se a oper­ação for pos­sív­el; ele retor­na fal­so se a oper­ação não for pos­sív­el.

x = 42;
var y = 43;
meuobj = new Number();
meuobj.h = 4;    // cria a propriedade h
delete x;        // retorna true (pode apagar se declarado implicitamente)
delete y;        // retorna false (não pode apagar se declarado com var)
delete Math.PI;  // retorna false (não pode apagar propriedades predefinidas)
delete meuobj.h; // retorna true (pode apagar propriedades definidas pelo usuário)
delete meuobj;   // retorna true (pode apagar se declarado implicitamente)
Apagando elementos de array

Quan­do você apa­ga um ele­men­to de um array, o taman­ho do array não é afe­ta­do. Por exem­p­lo, se você apa­ga a[3], o val­or de a[4] ain­da estará em a[4] e a[3] pas­sa a ser undefined.

Quan­do o oper­ador delete remove um ele­men­to do array, aque­le ele­men­to não per­tence mais ao array. No exem­p­lo a seguir, arvores[3] é removi­do com delete. Entre­tan­to, arvores[3] ain­da é endereçáv­el e retor­na undefined.

var arvores = new Array("pau-brasil", "loureiro", "cedro", "carvalho", "sicômoro");
delete arvores[3];
if (3 in arvores) {
  // isto não é executado
}

Se você quer que um ele­men­to do array exista, mas ten­ha um val­or indefinido, uti­lize a palavra-chave undefined em vez do oper­ador delete. No exem­p­lo a seguir, o val­or undefined é atribuí­do a arvores[3], mas o ele­men­to da matriz ain­da existe:

var arvores = new Array("pau-brasil", "loureiro", "cedro", "carvalho", "sicômoro");
arvores[3] = undefined;
if (3 in arvores) {
  // isto será executado
}

typeof

O oper­ador typeof é uti­liza­do em qual­quer uma das seguintes for­mas:

typeof operando
typeof (operando)

O oper­ador typeof retor­na uma string indi­can­do o tipo do operan­do sem avali­ação. operando é uma string, var­iáv­el, palavra-chave ou obje­to cujo tipo deve ser retor­na­do. Os parên­te­ses são opcionais.

Supon­ha que você defi­na as seguintes var­iáveis:

var meuLazer = new Function("5 + 2");
var forma = "redondo";
var tamanho = 1;
var hoje = new Date();

O oper­ador typeof retornar­ia o seguinte resul­ta­do para aque­las var­iáveis:

typeof meuLazer;  // retorna "function"
typeof forma;     // retorna "string"
typeof tamanho;   // retorna "number"
typeof hoje;      // retorna "object"
typeof naoExiste; // retorna "undefined"

Para as palavras-chave true e null, o typeof retor­na os seguintes resul­ta­dos:

typeof true; // retorna "boolean"
typeof null; // retorna "object"

Para um número ou uma string, o typeof retor­na os seguintes resul­ta­dos:

typeof 62;          // retorna "number"
typeof 'Olá mundo'; // retorna "string"

Para val­ores de pro­priedades, o typeof retor­na o tipo do val­or que a pro­priedade pos­sui:

typeof document.lastModified; // retorna "string"
typeof window.length;         // retorna "number"
typeof Math.LN2;              // retorna "number"

Para méto­dos e funções, o typeof retor­na os seguintes resul­ta­dos:

typeof blur;        // retorna "function"
typeof eval;        // retorna "function"
typeof parseInt;    // retorna "function"
typeof forma.split; // retorna "function"

Para obje­tos pre­definidos, o typeof retor­na os seguintes resul­ta­dos:

typeof Date;     // retorna "function"
typeof Function; // retorna "function"
typeof Math;     // retorna "object"
typeof Option;   // retorna "function"
typeof String;   // retorna "function"

void

O oper­ador void é uti­liza­do de qual­quer uma das seguintes for­mas:

void (expressao)
void expressao

O oper­ador void especi­fi­ca que uma expressão deve ser avali­a­da sem retorno de val­or. expressao é uma expressão JavaScript que deve ser avali­a­da. Os parên­te­ses em torno da expressão são opcionais, mas é uma boa práti­ca uti­lizá-los.

Você pode uti­lizar o oper­ador void para especi­ficar uma expressão como um link de hiper­tex­to. A expressão é avali­a­da mas não é car­rega­da no lugar do doc­u­men­to atu­al.

O códi­go a seguir cria um link de hiper­tex­to que não faz coisa algu­ma quan­do cli­ca­do pelo usuário. Quan­do o usuário cli­ca no link, void(0) é avali­a­do como indefinido, que não tem efeito em JavaScript.

<a href="javascript:void(0)">Clique aqui para fazer nada</a>

O códi­go a seguir cria um link de hiper­tex­to que sub­mete um for­mulário quan­do cli­ca­do pelo usuário.

<a href="javascript:void(document.form.submit())">
Clique aqui para enviar</a>

Operadores relacionais

Um oper­ador rela­cional com­para seus operan­do e retor­na um val­or booleano basea­do em se a com­para­ção é ver­dadeira.

in

O oper­ador in retor­na ver­dadeiro se a pro­priedade especi­fi­ca­da estiv­er no obje­to especi­fi­ca­do. A sin­taxe é:

nomePropriedadeOuNumero in nomeObjeto

onde nomePropriedadeOuNumero é uma string ou uma expressão numéri­ca que rep­re­sen­ta um nome de pro­priedade ou um índice de um array, e nomeObjeto é o nome de um obje­to.

Os exem­p­los a seguir mostram alguns usos do oper­ador in.

// Arrays
var arvores = new Array("pau-brasil", "loureiro", "cedro", "carvalho", "sicômoro");
0 in arvores;        // retorna verdadeiro
3 in arvores;        // retorna verdadeiro
6 in arvores;        // retorna falso
"cedro" in arvores;  // retorna falso (você deve especificar o número do índice,
                     // não o valor naquele índice)
"length" in arvores; // retorna verdadeiro (length é uma propriedade de Array)

// Objetos predefinidos
"PI" in Math;            // retorna verdadeiro
var minhaString = new String("coral");
"length" in minhaString; // retorna verdadeiro

// Objetos personalizados
var meucarro = {marca: "Honda", modelo: "Accord", ano: 1998};
"marca" in meucarro;  // retorna verdadeiro
"modelo" in meucarro; // retorna verdadeiro

instanceof

O oper­ador instanceof retor­na ver­dadeiro se o obje­to especi­fi­ca­do for do tipo de obje­to especi­fi­ca­do. A sin­taxe é:

nomeObjeto instanceof tipoObjeto

onde nomeObjeto é o nome do obje­to a ser com­para­do com tipoObjeto, e tipoObjeto é um tipo de obje­to como Date ou Array.

Uti­lize o instanceof quan­do você pre­cis­ar con­fir­mar o tipo de um obje­to em tem­po de exe­cução. Por exem­p­lo, ao cap­turar exceções você pode desviar para um códi­go de manip­u­lação de exceção difer­ente depen­den­do do tipo de exceção lança­da.

Por exem­p­lo, o códi­go a seguir uti­liza o instanceof para deter­mi­nar se dia é um obje­to Date. Como dia é um obje­to Date, as declar­ações do if são exe­cu­tadas.

var dia = new Date(1995, 12, 17);
if (dia instanceof Date) {
  // declarações a serem executadas
}

Precedência de operadores

pre­cedên­cia de oper­adores deter­mi­na a ordem em que eles são apli­ca­dos quan­do uma expressão é avali­a­da. Você pode sub­sti­tuir a pre­cedên­cia dos oper­adores uti­lizan­do parên­te­ses.

A tabela a seguir descreve a pre­cedên­cia de oper­adores, da mais alta para a mais baixa.

Tipo de oper­adorOper­adores indi­vid­u­ais
mem­bro. []
chama­da / cri­ação de instân­cia() new
negação / incre­men­to! ~ - + ++ -- typeof void delete
mul­ti­pli­cação / divisão / resto ou módu­lo* / %
adição / sub­tração+ -
deslo­ca­men­to bit a bit<< >> >>>
rela­cional< <= > >= in instanceof
igual­dade== != === !==
E bit a bit&
OU exclu­si­vo bit a bit^
OU bit a bit|
E lógi­co&&
OU lógi­co||
condi­cional?:
atribuição= += -= *= /= %= <<= >>= >>>= &= ^= |=
vír­gu­la,

Expressões

Uma expressão con­siste em qual­quer unidade vál­i­da de códi­go que é resolvi­da como um val­or.

Con­ceitual­mente, exis­tem dois tipos de expressões: aque­las que atribuem um val­or a uma var­iáv­el e aque­las que sim­ples­mente pos­suem um val­or.

A expressão x = 7 é um exem­p­lo do primeiro tipo. Esta expressão uti­liza o oper­ador = para atribuir o val­or sete à var­iáv­el x. A expressão em si é avali­a­da como sete.

O códi­go 3 + 4 é um exem­p­lo do segun­do tipo de expressão. Esta expressão uti­liza o oper­ador + para somar três e qua­tro sem atribuir o resul­ta­do, sete, a uma var­iáv­el.

O JavaScript pos­sui as seguintes cat­e­go­rias de expressão:

  • Arit­méti­ca: é avali­a­da como um número, por exem­p­lo 3.14159. (Geral­mente uti­liza oper­adores arit­méti­cos).
  • String: é avali­a­da como uma string de car­ac­teres, por exem­p­lo, “Fred” ou “234”. (Geral­mente uti­liza oper­adores de string).
  • Lóg­i­ca: é avali­a­da como ver­dadeira ou fal­sa. (Cos­tu­ma envolver oper­adores lógi­cos).
  • Expressões primárias: Palavras reser­vadas e expressões gerais do JavaScript.
  • Expressão lado esquer­do: atribuição à esquer­da de val­ores.

Expressões primárias

Palavras reser­vadas e expressões gerais do JavaScript.

this

Uti­lize a palavra reser­va­da this para se referir ao obje­to atu­al. Em ger­al, o this se ref­ere ao obje­to chama­do em um méto­do. Uti­lize o this das seguintes for­mas:

this["nomePropriedade"]
this.nomePropriedade

Supon­ha uma função chama­da valide que val­i­da a pro­priedade valor de um obje­to, dado o obje­to e os val­ores máx­i­mo e mín­i­mo:

function valide(obj, minimo, maximo){
  if ((obj.valor < minimo) || (obj.valor > maximo))
    alert("Valor inválido!");
}

Você pode­ria chamar valide em cada manip­u­lador de even­to onChange de um for­mulário uti­lizan­do this para pas­sar o ele­men­to do for­mulário, como no exem­p­lo a seguir:

<b>Informe um número entre 18 e 99:</b>
<input type="text" name="idade" size=3
   onChange="valide(this, 18, 99);">

Operador de agrupamento

O oper­ador de agru­pa­men­to ( ) con­tro­la a pre­cedên­cia de avali­ação de expressões. Por exem­p­lo, você pode sub­sti­tuir a pre­cedên­cia da divisão e mul­ti­pli­cação para que a adição e sub­tração sejam avali­adas primeiro.

var a = 1;
var b = 2;
var c = 3;

// Precedência padrão
a + b * c     // 7
// a avaliação padrão pode ser assim
a + (b * c)   // 7

// Agora substitui a precedência
// soma antes de multiplicar   
(a + b) * c   // 9

// o que é equivalente a
a * c + b * c // 9

Comprehensions

Com­pre­hen­sions são uma car­ac­terís­ti­ca exper­i­men­tal de JavaScript, mar­ca­da para ser inclusa em uma ver­são futu­ra do ECMAScript. Exis­tem duas ver­sões de Com­pre­hen­sions:

[for (x of y) x]
       Com­pre­hen­sions de array.

(for (x of y) y)
 gerador de com­pre­hen­sions

Com­pre­hen­sions exis­tem em muitas lin­gua­gens de pro­gra­mação e per­mitem que você rap­i­da­mente monte um novo array com base em um exis­tente, por exem­p­lo:

[for (i of [ 1, 2, 3 ]) i*i ]; 
// [ 1, 4, 9 ]

var abc = [ "A", "B", "C" ];
[for (letras of abc) letras.toLowerCase()];
// [ "a", "b", "c" ]

Expressão lado esquerdo

Atribuição à esquer­da de val­ores.

new

Você pode uti­lizar o oper­ador new para cri­ar uma instân­cia de um tipo de obje­to definido pelo usuário ou de um dos tipos de obje­to pre­definidos: ArrayBooleanDateFunctionImageNumberObjectOptionRegExp ou String. No servi­dor, você pode tam­bém uti­lizar DbPoolLockFile ou SendMail. Uti­lize o oper­ador new da seguinte for­ma:

var nomeObjeto = new tipoObjeto([parametro1, parametro2, ..., parametroN]);

super

A palavra reser­va­da super é uti­liza­da para chamar a função pai de um obje­to. É útil para nas class­es para a chama­da do con­stru­tor pai, por exem­p­lo:

super([argumentos]); //chama o construtor pai.
super.funcaoDoPai([argumentos]);

Operador spread

O oper­ador spread per­mite que uma expressão seja expandi­do em locais onde são esper­a­dos vários argu­men­tos (para chamadas de função) ou vários ele­men­tos (para arrays).

Exem­p­lo: Se você tem um array e dese­ja cri­ar um novo array com os ele­men­tos do array já exis­tente sendo parte do novo array, a sin­taxe do array não será sufi­ciente e você terá de usar uma com­bi­nação de push, splice, con­cat, etc. Com a sin­taxe spread, isto tor­na-se muito mais sucin­to:

var partes = ['ombro', 'joelhos'];
var musica = ['cabeca', ...partes, 'e', 'pés'];

Da mes­ma for­ma, o oper­ador spread fun­ciona com chamadas de função:

function f(x, y, z) { }
var args = [0, 1, 2];
f(...args);

Strings

O tipo String do JavaScript é usa­do para rep­re­sen­tar infor­mações de tex­to. É um con­jun­to de “ele­men­tos” com­pos­to por val­ores inteiros de 16-bits sem sinal. Cada ele­men­to den­tro da String ocu­pa uma posição den­tro dessa String. O primeiro ele­men­to está no índice 0, o próx­i­mo no índice 1, e assim suces­si­va­mente. O taman­ho de uma String é a quan­ti­dade de ele­men­tos que ela pos­sui. Você pode cri­ar strings usan­do strings lit­erais ou obje­tos string.

Strings literais

Você pode cri­ar strings usan­do aspas sim­ples ou aspas duplas:

'foo'
"bar"

Strings mais avançadas podem ser cri­adas usan­do sequên­cias de escape:

Sequências de escape hexadecimais

O número depois de \x é inter­pre­ta­do como um número hexa­dec­i­mal.

'\xA9' // "©"

Sequências de escape unicode

As sequên­cias de escape uni­code requerem no mín­i­mo qua­tro car­ac­teres depois do \u.

'\u00A9' // "©"

Sequências de escape Unicode code point

É novo no ECMAScript 6. Com essas sequên­cias, cada car­ac­tere pode ser “escapa­do” usan­do números hexa­dec­i­mais, sendo pos­sív­el usar pon­tos de códi­go Uni­code de até 0x10FFFF. Com escapes Uni­code sim­ples muitas vezes é necessário escr­ev­er as metades sub­sti­tu­tas sep­a­rada­mente para obter o mes­mo resul­ta­do.

Veja tam­bém String.fromCodePoint() or String.prototype.codePointAt().

'\u{2F804}'

// o mesmo com escapes Unicode simples
'\uD87E\uDC04'

Objetos String

O obje­to String é como uma “capa” ao redor do tipo prim­i­ti­vo string.

var s = new String("foo"); // Cria um objeto String
console.log(s); // Exibe no console: { '0': 'f', '1': 'o', '2': 'o'}
typeof s; // Retorna 'object'

Você pode chamar qual­quer um dos méto­dos do obje­to String em cima de uma string lit­er­al — JavaScript auto­mati­ca­mente con­verte a string lit­er­al em um obje­to String tem­porário, chama o méto­do, e então descar­ta o obje­to String tem­porário. Você pode tam­bém usar a pro­priedade String.length com uma string lit­er­al.

Você deve usar strings lit­erais a menos que você real­mente pre­cise usar um obje­to String, pois obje­tos String podem ter com­por­ta­men­tos ines­per­a­dos. Por exem­p­lo:

var s1 = "2 + 2"; // Cria uma string literal
var s2 = new String("2 + 2"); // Creates um objeto String
eval(s1); // Retorna o número 4
eval(s2); // Retorna a string "2 + 2"

Um obje­to String pos­sui uma pro­priedade, length, que indi­ca o número de car­ac­teres na string. Por exem­p­lo, o códi­go a seguir atribui o val­or 11 à var­iáv­el x, pois “Olá, mun­do!” pos­sui 11 car­ac­teres:

var minhaString = "Olá, mundo!";
var x = minhaString.length;

Um obje­to String pos­sui uma var­iedade de méto­dos: por exem­p­lo aque­les que retor­nam uma vari­ação da própria string, como substring e toUpperCase.

A tabela a seguir lista os méto­dos de obje­tos String.

Méto­doDescrição
charAtcharCodeAtcodePointAtRetor­na o códi­go do car­ac­tere ou o car­ac­tere em uma posição especí­fi­ca na string.
indexOflastIndexOfRetor­na a posição de uma sub­string especí­fi­ca na string ou a últi­ma posição da sub­string especí­fi­ca, respec­ti­va­mente.
startsWithendsWithincludesRetor­na se uma string começa, ter­mi­na ou con­tém uma out­ra string especí­fi­ca.
concatCon­cate­na o tex­to de duas strings e retor­na uma nova string.
fromCharCodefromCodePointCria uma string a par­tir de uma sequên­cia especí­fi­ca de val­ores Uni­code. Esse é um méto­do da classe String, não de uma instân­cia do tipo String.
splitSep­a­ra um obje­to String em um array de strings, sep­a­ran­do a string em sub­strings.
sliceExtrai uma seção de uma string e retor­na uma nova string.
substringsubstrRetor­na um sub­con­jun­to especí­fi­co de uma string, definin­do os índices ini­cial e final, ou definin­do um índice e um taman­ho.
matchreplacesearchTra­bal­ha com expressões reg­u­lares.
toLowerCasetoUpperCaseRetor­na a string com todos car­ac­teres em minús­cu­lo, ou maiús­cu­lo, respec­ti­va­mente.
normalizeRetor­na a For­ma Nor­mal­iza­da Uni­code (Uni­code Nor­mal­iza­tion Form) da string que chama o méto­do.
repeatRetor­na uma string con­tendo os ele­men­tos do obje­to repeti­dos pela quan­ti­dade de vezes dada.
trimReti­ra espaços em bran­co no começo e no final da string.

Template strings com várias linhas

Tem­plate strings são strings lit­erais que per­mitem expressões no seu con­teú­do. Você pode usar os recur­sos de strings com mul­ti­plas lin­has e inter­po­lações de string com as tem­plate strings.

Tem­plate strings são declar­adas com o acen­to grave (“) ao invés de aspas sim­ples ou aspas duplas. Essas strings podem con­ter place hold­ers. Os place hold­ers são indi­ca­dos pelo cifrão e com chaves ( ${expressao} ).

Várias linhas (Multi-lines)

Qual­quer car­ac­tere de nova lin­ha ( '\n' ) inseri­do na string tam­bém faz parte das tem­plate string. Usan­do strings nor­mais, você teria que usar a sin­taxe a seguir para con­seguir uma string de várias lin­has

console.log("linha de texto 1\n\
linha de texto 2");
// "linha de texto 1
// linha de texto 2"

Para obter o mes­mo efeito com strings mul­ti-lines, você pode ago­ra escr­ev­er:

console.log(`linha de texto 1
linha de texto 2`);
// "linha de texto 1
// linha de texto 2"

Expressões inseridas

Para con­seguir inserir expressões com strings nor­mais, você teria que usar a seguinte sin­taxe:

var a = 5;
var b = 10;
console.log("Quinze é " + (a + b) + " e\nnão " + (2 * a + b) + ".");
// "Quinze é 15 e
// não 20."

Ago­ra, com tem­plate strings, você tem a capaci­dade de usar uma for­ma mais sim­ples e legív­el para faz­er essas sub­sti­tu­ições:

var a = 5;
var b = 10;
console.log(`Quinze é ${a + b} e\nnão ${2 * a + b}.`);
// "Quinze é 15 e 
// não 20."

Internacionalização

O obje­to Intl é o name­space para a API de Inter­na­cional­iza­ção do ECMAScript, que ofer­ece com­para­ção de strings sen­síveis à lin­guagem, for­matação de números, e for­matação de datas e horas. Os con­stru­tores para os obje­tos CollatorNumberFormat, e DateTimeFormat são pro­priedades do obje­to Intl.

Formatação de data e hora

O obje­to DateTimeFormat é útil para a for­matação de data e hora. O códi­go a seguir for­ma­ta uma data em inglês no for­ma­to que é uti­liza­do nos Esta­dos Unidos. (O resul­ta­do é difer­ente em out­ro fuso horário).

var msPorDia = 24 * 60 * 60 * 1000; // número de milisegundos em um dia
 
// July 17, 2014 00:00:00 UTC.
var july172014 = new Date(msPorDia * (44 * 365 + 11 + 197));

var opcoes = { year: "2-digit", month: "2-digit", day: "2-digit",
                hour: "2-digit", minute: "2-digit", timeZoneName: "short" };
var americanDateTime = new Intl.DateTimeFormat("en-US", opcoes).format;
 
console.log(americanDateTime(july172014)); // 07/16/14, 5:00 PM PDT

Formatação de números

O obje­to NumberFormat é útil para for­matar números, por exem­p­lo unidade mon­etária.

var precoGasolina = new Intl.NumberFormat("en-US",
                        { style: "currency", currency: "USD",
                          minimumFractionDigits: 3 });
 
console.log(precoGasolina.format(5.259)); // $5.259

var hanDecimalRMBInChina = new Intl.NumberFormat("zh-CN-u-nu-hanidec",
                        { style: "currency", currency: "CNY" });
 
console.log(hanDecimalRMBInChina.format(1314.25)); // ¥ 一,三一四.二五

Collation

O obje­to Collator é usa­do para com­parar e ordenar strings.

Por exem­p­lo, exis­tem atual­mente duas ordens difer­entes de clas­si­fi­cação no Alemão: lis­taTele­fôni­ca e dicionário. A orde­nação da lis­taTele­fôni­ca enfa­ti­za o som, e é como se “ä”, “ö”, e assim por diante, fos­sem expandi­dos para “ae”, “oe”, e assim suces­si­va­mente, para definir a ordem.

var nomes = ["Hochberg", "Hönigswald", "Holzman"];
 
var phonebookAlemao = new Intl.Collator("de-DE-u-co-phonebk");
 
// como se ordenasse ["Hochberg", "Hoenigswald", "Holzman"]:
console.log(names.sort(phonebookAlemao.compare).join(", "));
// imprime "Hochberg, Hönigswald, Holzman"

Algu­mas palavras do alemão são con­ju­gadas com tremas extras, mas no dicionário essas palavras são orde­nadas igno­ran­do os tremas (exce­to quan­do orde­nan­do palavras que tem ape­nas o trema como difer­ença: schon antes de schön).

var dicionarioAlemao = new Intl.Collator("de-DE-u-co-dict");
 
// como se ordenasse ["Hochberg", "Honigswald", "Holzman"]:
console.log(names.sort(dicionarioAlemao.compare).join(", "));
// imprime "Hochberg, Holzman, Hönigswald"

.

Objeto Array

Um array é um con­jun­to de val­ores orde­na­dos que você o ref­er­en­cia com um nome e um índice. Por exem­p­lo, você pode ter um array chama­do emp que con­tém nomes de fun­cionários index­a­dos por seus números de fun­cionários. Então emp[1] pode­ria ser o fun­cionário número 1, emp[2] o fun­cionário número 2 e assim por diante.

JavaScript não pos­sui um tipo de dados array especí­fi­co. No entan­to, você pode usar  o obje­to pre­definido Array e seus méto­dos para tra­bal­har com arrays em suas apli­cações. O obje­to Array tem méto­dos para manip­u­lar arrays de várias maneiras como join, reverse e sort. Ele tem uma pro­priedade para deter­mi­nar o taman­ho do array e out­ras pro­priedades para usar com expressões reg­u­lares.

Criando um array

As declar­ações a seguir cri­am arrays equiv­a­lentes:

var arr = new Array(elemento0, elemento1, ..., elementoN);
var arr = Array(elemento0, elemento1, ..., elementoN);
var arr = [elemento0, elemento1, ..., elementoN];

elemento0, elemento1, ..., elementoN é uma lista de val­ores para os ele­men­tos do array. Quan­do ess­es val­ores são especi­fi­ca­dos, o array é ini­cial­iza­do com eles como ele­men­tos deste array. A pro­priedade do com­pri­men­to do array é defini­da pelo número de argu­men­tos.

A sin­taxe dos colchetes é chama­da de “array lit­er­al” ou “ini­cial­izador de array”. É uma abre­vi­ação de out­ras for­mas de cri­ação de array e é a for­ma preferi­da de cri­ação. Veja  Array lit­er­al para detal­h­es.

Para cri­ar um array com taman­ho difer­ente de zero mas sem nen­hum item, qual­quer esque­ma abaixo pode ser uti­liza­do:

var arr = new Array(comprimentoDoArray);
var arr = Array(comprimentoDoArray);

// Estes produzem exatamente o mesmo efeito
var arr = [];
arr.length = comprimentoDoArray;

Nota : No códi­go aci­ma, comprimentoDoArray deve ser um Número. De out­ra maneira, um array com um úni­co ele­men­to (o val­or pas­sa­do) será cri­a­do. Chamar arr.length retornará comprimentoDoArray, mas o array na ver­dade, con­tem ele­men­tos vazios (unde­fined). Exe­cu­tar um loop for...in no array, não retornará nen­hum dos ele­men­tos do array.

Além de poderem ser definidos como uma nova var­iáv­el, como mostra­do aci­ma, arrays tam­bém podem ser atribuí­dos como uma pro­priedade de um novo obje­to, ou de um obje­to exis­tente:

var obj = {};
// ...
obj.prop = [elemento0, elemento1, ..., elementoN];

// OU
var obj = {prop: [elemento0, elemento1, ...., elementoN]}

Se você dese­ja ini­cializar um array com um úni­co ele­men­to, e este ele­men­to é um Número, você pre­cisa usar a sin­táxe dos colchetes. Quan­do um úni­co val­or de Número é pas­sa­do para o con­stru­tor do Array(), ou para uma função, ele é inter­pre­ta­do como um comprimentoDoArray, e não como um ele­men­to úni­co.

var arr = [42];      // Cria um array com apenas um elemento:
                     // o número 42.

var arr = Array(42); // Cria um array sem elementos
                     // e arr.length é definido como 42; isso é
                     // equivalente a:
var arr = [];
arr.length = 42;

Chamar Array(N) resul­ta  em um RangeError, se N é um número não inteiro cuja porção fra­cionária não é zero. O exem­p­lo a seguir ilus­tra esse com­por­ta­men­to.

var arr = Array(9.3);  // RangeError: Invalid array length

Se o seu códi­go pre­cisa cri­ar arrays com ele­men­tos sin­gu­lares de um tipo de dados arbi­trário, é mais seguro usar arrays lit­erais. Ou então, crie um array vazio antes de adi­cionar um ele­men­to sin­gu­lar nele.

Povoando um array

Você pode povoar (inserir ele­men­tos) a um array atribuin­do val­ores aos seus ele­men­tos. Por exem­p­lo,

var emp = [];
emp[0] = 'Casey Jones';
emp[1] = 'Phil Lesh';
emp[2] = 'August West';

Nota : se você fornece um val­or não inteiro ao oper­ador do array, como no códi­go aci­ma, a pro­priedade será cri­a­da no obje­to rep­re­sen­tan­do o array, ao invés do ele­men­to do array.

var arr = [];
arr[3.4] = 'Oranges';
console.log(arr.length);                // 0
console.log(arr.hasOwnProperty(3.4));   // verdadeiro

Você tam­bém pode povoar o array quan­do o cria:

var myArray = new Array('Olá', myVar, 3.14159);
var myArray = ['Manga', 'Maçã', 'Laranja']

Referenciando os elementos do array

Você ref­er­en­cia os ele­men­tos do array através do uso de ele­men­tos numéri­cos ordi­nais. Por exem­p­lo, supon­ha que você definiu o seguinte array:

var myArray = ['Vento', 'Chuva', 'Fogo'];

Você então se ref­ere ao primeiro ele­men­to do array como em myArray[0] e ao segun­do ele­men­to do array como em myArray[1]. O índice do ele­men­to começa com zero.

Nota : o oper­ador do array (colchetes) tam­bém é usa­do para aces­sar as pro­priedades do array (arrays tam­bém são obje­tos em JavaScript). Por exem­p­lo,

var arr = ['um', 'dois', 'três'];
arr[2];         // três
arr['length'];  // 3

Compreendendo o comprimento

Sobe o pon­to de vista da imple­men­tação, arrays JavaScript armazenam na real­i­dade ele­men­tos como pro­priedades de obje­tos padrões, usan­do o índice do array como o nome da pro­priedade. O com­pri­men­to da pro­priedade é espe­cial: ele sem­pre retor­na o índice do últi­mo mais um (no exem­p­lo seguinte Dusty é index­a­do no 30, então  cats.length retor­na 30 + 1). Lem­bre-se, índices de arrays JavaScript são basea­d­os no zero: eles começam no 0, não no 1. Isso sig­nifi­ca que  o com­pri­men­to da pro­priedade será um a mais que o maior índice armazena­do no array:

var gatos = [];
gatos[30] = ['Dusty'];
console.log(gatos.length); // 31

Você tam­bém pode atribuir um val­or à pro­priedade length. Ao escr­ev­er um val­or menor que o número de itens armazena­dos, trun­ca o array: escreven­do zero limpa‑o com­ple­ta­mente:

var gatos = ['Dusty', 'Misty', 'Twiggy'];
console.log(gatos.length); // 3

gatos.length = 2;
console.log(gatos); // mostra "Dusty, Misty" - Twiggy foi removido

gatos.length = 0;
console.log(gatos); // nada é apresentado; o array gatos está vazio

gatos.length = 3;
console.log(gatos); // [undefined, undefined, undefined]

Iteração em arrays

Uma oper­ação comum é a de iter­ar sobre os val­ores de um array, proces­san­do cada ele­men­to de algu­ma maneira. A maneira mais sim­ples para faz­er isso é como segue:

var cores = ['vermelho', 'verde', 'azul'];
for (var i = 0; i < cores.length; i++) {
  console.log(cores[i]);
}

Se você sabe que nen­hum dos elem­ne­tos no seu array é avali­a­do como false em um con­tex­to booleano  — se o seu array con­siste ape­nas de nodos do DOM, como exem­p­lo, você pode usar um idioma mais efi­ciente:

var divs = document.getElementsByTagName('div');
for (var i = 0, div; div = divs[i]; i++) {
  /* Processa div de alguma forma */
}

Isso evi­ta a sobre­car­ga da checagem do com­pri­men­to do array, e garante que a var­iáv­el div seja reatribui­da ao item atu­al cada vez que o loop for adi­ciona­do por con­veniên­cia.

O méto­do forEach() disponi­bi­liza um out­ro jeito de iter­ar sobre/em um array:

var cores = ['vermelho', 'verde', 'azul'];
cores.forEach(function(cor) {
  console.log(cor);
});
// vermelho
// verde
// azul

Alter­na­ti­va­mente, você pode encur­tar o códi­go para o parâmetro do forEach com Arrow Func­tions ES6.

var cores = ['vermelho', 'verde', 'azul'];
cores.forEach(cor => console.log(cor)); 
// vermelho
// verde
// azul

A função pas­sa­da para o forEach é exe­cu­ta­da uma vez para cada item no array, com o item do array pas­sa­do como o argu­men­to para a função. Val­ores não atribuí­dos não são iter­a­dos no loop forEach.

Note que os ele­men­tos de um array que foram omi­ti­dos quan­do o array foi definido, não são lis­ta­dos quan­do iter­a­dos pelo forEach, mas são lis­ta­dos quan­do undefined foi man­ual­mente atribuí­do ao ele­men­to:

var array = ['primeiro', 'segundo', , 'quarto'];

array.forEach(function(elemento) {
  console.log(elemento);
})
// primeiro
// segundo
// quarto

if (array[2] === undefined) {
  console.log('array[2] is undefined'); // verdadeiro
}

array = ['primeiro', 'segundo', undefined, 'quarto'];

array.forEach(function(elemento) {
  console.log(elemento);
});
// primeiro
// segundo
// undefined
// quarto

Como ele­men­tos JavaScript são salvos como pro­priedades de obje­tos padroniza­dos, não é acon­sel­háv­el iter­ar sobre arrays JavaScript usan­do loops for...in, porque ele­men­tos nor­mais e todas as pro­priedades numeráveis serão lis­tadas.

Métodos dos arrays

O obje­to Array pos­sui os seguintes méto­dos:

concat() une dois arrays e retor­na um novo array.

var myArray = new Array('1', '2', '3');
myArray = myArray.concat('a', 'b', 'c'); 
// myArray agora é ["1", "2", "3", "a", "b", "c"]

join(deliminator = ',') une todos os ele­men­tos de um array den­tro de um string.

var myArray = new Array('Vento', 'Chuva', 'Fogo');
var lista = myArray.join(' - '); // lista é "Vento - Chuva - Fogo"

push() adi­ciona um ou mais ele­men­tos no fim de um array e retor­na o com­pri­men­to resul­tante do array.

var myArray = new Array('1', '2');
myArray.push('3'); // myArray é agora ["1", "2", "3"]

pop() remove o últi­mo ele­men­to de um array e retor­na esse ele­men­to.

var myArray = new Array('1', '2', '3');
var ultimo = myArray.pop(); 
// myArray é agora ["1", "2"], ultimo = "3"

shift() remove o primeiro ele­men­to de um array e retor­na esse ele­men­to.

var myArray = new Array('1', '2', '3');
var primeiro = myArray.shift(); 
// myArray agora é ["2", "3"], primeiro é "1"

unshift() adi­ciona um ou mais ele­men­tos ao iní­cio do array e retor­na o novo com­pri­men­to do array.

var myArray = new Array('1', '2', '3');
myArray.unshift('4', '5'); 
// myArray torna-se ["4", "5", "1", "2", "3"]

slice(start_index, upto_index) extrai uma seção de um array e retor­na um novo array.

var myArray = new Array('a', 'b', 'c', 'd', 'e');
myArray = myArray.slice(1, 4); // inicia no índice 1 e extrai todos os elementos
                               // até o índice 3, retornado [ "b", "c", "d"]

splice(index, count_to_remove, addElement1, addElement2, ...) remove ele­men­tos de um array e (opcional­mente) o sub­sti­tui, e retor­na os itens que foram removi­dos do array.

var myArray = new Array('1', '2', '3', '4', '5');
myArray.splice(1, 3, 'a', 'b', 'c', 'd'); 
// myArray é agora ["1", "a", "b", "c", "d", "5"]
// Este código iniciou no índice um (ou onde o "2" estava),
// removeu 3 elementos a partir dali, e então inseriu todos os elementos
// consecutivos em seus lugares.

reverse() transpõe (inverte) os ele­men­tos de um array, in situ: o primeiro ele­men­to do array se tor­na o últi­mo e o últi­mo tor­na-se o primeiro, e retor­na uma refer­ên­cia para o array.

var myArray = new Array('1', '2', '3');
myArray.reverse(); 
// transpõe o array de modo que myArray = [ "3", "2", "1" ]

sort() orde­na os ele­men­tos de um array in situ, e retor­na uma refer­ên­cia para o array.

var myArray = new Array('Neve', 'Chuva', 'Fogo');
myArray.sort(); 
// ordena o array de modo que myArray = [ "Chuva", "Fogo", "Neve" ]

sort() tam­bém pode ‘pegar’ uma função call­back para deter­mi­nar como os ele­men­tos do array são com­para­dos.

O méto­do sort, assim como out­ros méto­dos abaixo que tomam um call­back são con­heci­dos como méto­dos iter­a­tivos, porque eles iter­am sobre o array de algu­ma for­ma. Cada um pega um segun­do argu­men­to opcional chama­do thisObject. Se forneci­do, thisObject se tor­na o val­or da palavra chave this den­tro do cor­po da função call­back. Se não forneci­do, como em out­ros casos onde uma função é invo­ca­da fora do con­tex­to explíc­i­to de um obje­to, this fará refer­ên­cia ao obje­to glob­al (window).

A função call­back é na ver­dade chama­da com três argu­men­tos. O primeiro é o val­or do item cor­rente, o segun­do é o índice do array e o ter­ceiro é uma refer­ên­cia ao próprio array. Funções javaScript igno­ram qual­quer argu­men­to que não são nomea­d­os na lista de parâmet­ros, por­tan­to é seguro prover uma função call­back que toma somente um úni­co argu­men­to, como a função alert.

A função abaixo com­para dois val­ores e retor­na um dos tres val­ores: ‑1, 0 ou 1.

Por exem­p­lo, o seguinte tre­cho de códi­go vai ordenar pela últi­ma letra da string:

var sortFn = function(a, b){
  if (a[a.length - 1] < b[b.length - 1]) return -1;
  if (a[a.length - 1] > b[b.length - 1]) return 1;
  if (a[a.length - 1] == b[b.length - 1]) return 0;
}
myArray.sort(sortFn); 
// ordena o array de modo que myArray = ["Chuva","Neve","Fogo"]
  • se a for menor que b pelo sis­tema de orde­nação, retor­na ‑1 (ou qual­quer número neg­a­ti­vo)
  • se a for maior que b pelo sis­tema de orde­nação, retor­na 1 (ou qual­quer número pos­i­ti­vo)
  • se a e b forem con­sid­er­a­dos equiv­a­lentes, return­ará 0.

indexOf(searchElement[, fromIndex]) bus­ca searchElement no array e retor­na o índice da primeira ocor­rên­cia.

var a = ['a', 'b', 'a', 'b', 'a'];
console.log(a.indexOf('b'));    // mostra 1
// Agora tente novamente, iniciando após o último resultado de busca
console.log(a.indexOf('b', 2)); // mostra 3
console.log(a.indexOf('z'));    // mostra -1, porque 'z' não foi encontrado

lastIndexOf(searchElement[, fromIndex]) fun­ciona como indexOf, mas começa no fim e bus­ca de trás para a frente.

var a = ['a', 'b', 'c', 'd', 'a', 'b'];
console.log(a.lastIndexOf('b'));    // mostra 5
// Agora tente novamente, iniciando antes do último resultado de busca
console.log(a.lastIndexOf('b', 4)); // mostra 1
console.log(a.lastIndexOf('z'));    // mostra -1

forEach(callback[, thisObject]) exe­cu­ta um callback em cada item do array e retor­na unde­fined.

var a = ['a', 'b', 'c'];
a.forEach(function(element) { console.log(elemento); });
// mostra cada item por vez

map(callback[, thisObject]) retor­na um novo array do val­or retor­na­do da exe­cução do call­back em cada item do array.

var a1 = ['a', 'b', 'c'];
var a2 = a1.map(function(item) { return item.toUpperCase(); });
console.log(a2); // logs ['A', 'B', 'C']

filter(callback[, thisObject]) retor­na um novo array con­tendo os items ver­dadeiros ao exe­cu­tar o call­back.

var a1 = ['a', 10, 'b', 20, 'c', 30];
var a2 = a1.filter(function(item) { return typeof item === 'number'; });
console.log(a2); // mostra [10, 20, 30]

every(callback[, thisObject]) retor­na ver­dadeiro se o callback retornar ver­dadeiro para cada item no array.

function isNumber(valor) {
  return typeof valor === 'number';
}
var a1 = [1, 2, 3];
console.log(a1.every(isNumber)); // mostra true
var a2 = [1, '2', 3];
console.log(a2.every(isNumber)); // mostra false

some(callback[, thisObject]) retor­na ver­dadeiro se o callback retornar ver­dadeiro para pelo menos um item no array.

function isNumber(valor) {
  return typeof valor === 'number';
}
var a1 = [1, 2, 3];
console.log(a1.some(isNumber)); // mostra true
var a2 = [1, '2', 3];
console.log(a2.some(isNumber)); // mostra true
var a3 = ['1', '2', '3'];
console.log(a3.some(isNumber)); // mostra false

reduce(callback[, initialValue]) apli­ca callback(firstValue, secondValue) para reduzir a lista de itens para um úni­co val­or e retor­na este val­or.

var a = [10, 20, 30];
var total = a.reduce(function(primeiro, segundo) { return primeiro + segundo; }, 0);
console.log(total) // mostra 60

reduceRight(callback[, initalvalue]) fun­ciona como reduce(), mas ini­cia com o últi­mo ele­men­to.

reduce e reduceRight são os méto­dos iter­a­tivos menos óbvios dos arrays. Eles devem ser usa­dos para algo­rít­mos que com­bi­nam dois val­ores de maneira recur­si­va com a final­i­dade de reduzir uma sequên­cia para um úni­co val­or.

Arrays multidimensionais

Arrays podem ser anin­hados, sig­nif­i­can­do que um array pode con­ter out­ro array como seu ele­men­to. Usan­do essa car­ac­terís­ti­ca dos arrays JavaScript, arrays mul­ti­di­men­sion­ais pode ser cri­a­dos.

O códi­go a seguir cria dois arrays mul­ti­di­men­sion­ais:

var a = new Array(4);
for (i = 0; i < 4; i++) {
  a[i] = new Array(4);
  for (j = 0; j < 4; j++) {
    a[i][j] = '[' + i + ',' + j + ']';
  }
}

Esse exem­p­lo cria um array com as seguintes lin­has:

Linha 0: [0,0] [0,1] [0,2] [0,3]
Linha 1: [1,0] [1,1] [1,2] [1,3]
Linha 2: [2,0] [2,1] [2,2] [2,3]
Linha 3: [3,0] [3,1] [3,2] [3,3]

Arrays e expressões regulares

Quan­do um array é o resul­ta­do de uma equiv­alên­cia entre uma expressão reg­u­lar e um string, o array retor­na pro­priedades e ele­men­tos que disponi­bi­lizam a infor­mação sobre a cor­re­spondên­cia. Um array é o val­or retor­na­do de RegExp.exec()String.match(), e String.split(). Para infor­mações sobre o uso de arrays com expressões reg­u­lares, veja Expressões Reg­u­lares.

Trabalhando com objetos array-like

Alguns obje­tos JavaScript, como a NodeList retor­na­da pelo document.getElementsByTagName() ou o obje­to acessív­el den­tro do arguments de uma função, se pare­cem e se com­por­tam super­fi­cial­mente como arrays, mas não com­par­til­ham de todos os seus méto­dos. O obje­to arguments fornece um atrib­u­to length mas não imple­men­ta o méto­do forEach(), por exem­p­lo.

Méto­dos Array pro­to­type podem ser chama­dos con­tra out­ros obje­tos array-like. Por exem­p­lo:

function printArguments() {
  Array.prototype.forEach.call(arguments, function(item) {
    console.log(item);
  });
}

Méto­dos Array pro­to­type tam­bém podem ser usa­dos em strings, des­de que eles forneçam aces­so sequen­cial a seus car­ac­teres de maneira sim­i­lar às arrays:

Array.prototype.forEach.call('uma string', function(chr) {
  console.log(chr);
});

Arrays Tipados

Arrays tipa­dos no JavaScript são obje­tos array-like e provêm um mecan­is­mo para aces­sar dados binários crus. Como você já sabe, obje­tos Array crescem e encol­hem dinami­ca­mente e podem ter um val­or JavaScript. O motor do JavaScript exe­cu­ta otimiza­ções para que os arrays sejam rápi­dos. Con­tu­do, à medi­da que as apli­cações web se tor­nam cada vez mais poderosas, com a adição de fun­cional­i­dades como manip­u­lação de áudio e vídeo, aces­so a dados crus usan­do Web­Sock­ets, etc., ficou claro que exis­tem momen­tos em que seria útil para o códi­go JavaScript ser capaz de rap­i­da e facil­mente manip­u­lar dados binários crus em arrays tipa­dos.

Buffers e views: arquitetura do array tipado

Para alcançar máx­i­ma flex­i­bil­i­dade e efi­ciên­cia, as views de array tipa­do do JavaScript divi­dem a imple­men­tação em buffers e views. Um buffer (imple­men­ta­do pelo obje­to ArrayBuffer) é um obje­to que rep­re­sen­ta um monte de dados; não pos­sui nen­hum for­ma­to especí­fi­co e não ofer­ece nen­hum mecan­is­mo para aces­sar seu con­teú­do. Para aces­sar a memória con­ti­da em um buffer, você pre­cisa usar uma view. Uma view provê um con­tex­to — ou seja, um tipo de dado, um off­set ini­cial e número de ele­men­tos — que trans­for­ma o dado em um array tipa­do real.

Typed arrays in an ArrayBuffer

ArrayBuffer

ArrayBuffer é um tipo de dado usa­do para rep­re­sen­tar um buffer de dados binários de taman­ho fixo genéri­co. Você não pode manip­u­lar dire­ta­mente o con­teú­do de um ArrayBuffer; ao invés dis­so, você deve cri­ar uma view de array tipa­do ou uma DataView que rep­re­sente o buffer em um for­ma­to especí­fi­co, e use esta view para ler e mod­i­ficar o con­teú­do do buffer.

Views de arrays tipados

Views de arrays tipa­dos pos­suem nomes autode­s­critivos e provêm views para todos os tipos numéri­cos usuais como Int8Uint32Float64 e assim por diante. Existe uma view de array tipa­do espe­cial, o Uint8ClampedArray. Ela fixa os val­ores entre 0 e 255. Isto é útil para Can­vas data pro­cess­ing, por exem­p­lo.

TypeVal­ue RangeSize in bytesDescrip­tionWeb IDL typeEquiv­a­lent C type
Int8Array-128 to 12718‑bit two’s com­ple­ment signed inte­gerbyteint8_t
Uint8Array0 to 25518‑bit unsigned inte­geroctetuint8_t
Uint8ClampedArray0 to 25518‑bit unsigned inte­ger (clamped)octetuint8_t
Int16Array-32768 to 32767216-bit two’s com­ple­ment signed inte­gershortint16_t
Uint16Array0 to 65535216-bit unsigned inte­gerunsigned shortuint16_t
Int32Array-2147483648 to 2147483647432-bit two’s com­ple­ment signed inte­gerlongint32_t
Uint32Array0 to 4294967295432-bit unsigned inte­gerunsigned longuint32_t
Float32Array1.2x10-38 to 3.4x1038432-bit IEEE float­ing point num­ber ( 7 sig­nif­i­cant dig­its e.g. 1.1234567)unrestricted floatfloat
Float64Array5.0x10-324 to 1.8x10308864-bit IEEE float­ing point num­ber (16 sig­nif­i­cant dig­its e.g. 1.123…15)unrestricted doubledouble

Posts Similares