Adicionando recursos à nossa demonstração de bolas pulantes - Aprendendo desenvolvimento web

Adicionando recursos à nossa demonstração de bolas pulantes
===========================================================

* Anterior
* Menu: Objects

Nesta avaliação, espera-se que você use a demonstração de bolas saltantes do artigo anterior como ponto de partida e adicione alguns recursos novos e interessantes a ela.

|  |  |
| --- | --- |
| Prerequisites: |
 Before attempting this assessment you should have already worked through
 all the articles in this module.
  |
| Objective: |
 To test comprehension of JavaScript objects and object-oriented
 constructs
  |

Ponto de partida
----------------

Para iniciar essa avaliação, faça uma cópia local de index-finished.html, style.css, e main-finished.js do nosso último artigo em um novo diretório em seu computador local.

**Nota:** Alternatively, you could use a site like JSBin or Thimble to do your assessment. You could paste the HTML, CSS and JavaScript into one of these online editors. If the online editor you are using doesn't have separate JavaScript/CSS panels, feel free to put them inline `<script>`/`<style>` elements inside the HTML page.

Resumo do projeto
-----------------

Nossa demo com bola saltitante é divertida, mas agora queremos torná-la um pouco mais interativa, adicionando um círculo maligno controlado pelo usuário, que vai comer as bolas se elas forem capturadas. Também queremos testar suas habilidades de construção de objetos criando um objeto `Shape()` genérico do qual nossas bolas e círculo maligno podem herdar. Por fim, queremos adicionar um contador de pontuação para rastrear o número de bolas a serem capturadas.

A imagem seguinte dá-lhe uma ideia do que deve ser o programa final:

![](/pt-BR/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features/bouncing-evil-circle.png)

Para lhe dar mais uma ideia, dê uma olhada no exemplo finalizado (não espreitar o código-fonte!)

Passos para concluir
--------------------

As seções a seguir descrevem o que você precisa fazer.

### Criando nossos novos objetos

Primeiro de tudo, altere seu construtor `Ball()` existente para que ele se torne um construtor `Shape()` e adicione um novo construtor `Ball()`:

1. O construtor `Shape()` deve definir as propriedades `x`, `y`, `velX`, e `velY` da mesma maneira que o construtor `Ball()` fez originalmente, mas não as propriedades de `color` e `size`.
2. Também deve definir uma nova propriedade chamada `exists`, que é usada para rastrear se as bolas existem no programa (não foram comidas pelo círculo do mal). Este deve ser um booleano (`true`/`false`).
3. O construtor `Ball()` deve herdar as propriedades `x`, `y`, `velX`, `velY`, e `exists` do construtor `Shape()`.
4. Ele também deve definir uma propriedade `color` e uma `size`, como fez o construtor `Ball()` original.
5. Lembre-se de definir o `prototype` e o `constructor` do construtor `Ball()` adequadamente.

As definições do método ball `draw()`, `update()`, e `collisionDetect()` devem permanecer exatamente iguais às anteriores.

Você também precisa adicionar um novo parâmetro à nova chamada de construtor `new Ball() ( ... )` — o parâmetro `exists` deve ser o quinto parâmetro, e deve receber um valor `true`.

Neste ponto, tente recarregar o código — ele deve funcionar da mesma forma que antes, com nossos objetos redesenhados.

### Definindo EvilCircle()

Agora é hora de conhecer o cara mau — o `EvilCircle()`! Nosso jogo só envolverá um círculo maligno, mas ainda vamos defini-lo usando um construtor que herda de `Shape()` para lhe dar alguma prática. Você pode querer adicionar outro círculo ao aplicativo mais tarde, que pode ser controlado por outro jogador, ou ter vários círculos malignos controlados por computador. Você provavelmente não vai dominar o mundo com um único círculo maligno, mas fará por essa avaliação.

O construtor `EvilCircle()` deve herdar `x`, `y`, `velX`, `velY`, e `exists` de `Shape()`, mas `velX` e `velY` devem sempre ser iguais a 20.

Você deveria fazer algo como `Shape.call(this, x, y, 20, 20, exists);`

Ele também deve definir suas próprias propriedades, da seguinte maneira:

* `color` — `'white'`
* `size` — `10`

Novamente, lembre-se de definir suas propriedades herdadas como parâmetros no construtor e defina as propriedades `prototype` e `constructor` corretamente.

### Definindo os métodos de EvilCircle()

`EvilCircle()` deve ter quatro métodos, conforme descrito abaixo.

#### `draw()`

Este método tem o mesmo propósito que o método `draw()` de `Ball()`: Ele desenha a instância do objeto na tela. Ele funcionará de maneira muito semelhante, portanto, você pode começar copiando a definição `Ball.prototype.draw`. Você deve então fazer as seguintes alterações:

* Nós queremos que o círculo do mal não seja preenchido, mas apenas tenha uma linha externa (traço). Você pode conseguir isso atualizando `fillStyle` e `fill()` para `strokeStyle` (en-US) e `stroke()`.
* Também queremos tornar o traço um pouco mais espesso, para que você possa ver o círculo maligno com mais facilidade. Isso pode ser obtido definindo um valor para `lineWidth` (en-US) em algum lugar após a chamada `beginPath()` (3 será suficiente).

#### `checkBounds()`

Este método fará a mesma coisa que a primeira parte da função `update()` do `Ball()` — olhe para ver se o círculo do mal vai sair da borda da tela, e pare de fazer isso. Novamente, você pode simplesmente copiar a definição de `Ball.prototype.update`, mas há algumas alterações que você deve fazer:

* Livre-se das duas últimas linhas - não queremos atualizar automaticamente a posição do círculo maligno em todos os quadros, pois estaremos mudando isso de alguma outra forma, como você verá abaixo.
* Dentro das instruções `if()`, se os testes retornam true, não queremos atualizar o `velX`/`velY`; Em vez disso, queremos alterar o valor de `x`/`y` para que o círculo maligno seja devolvido na tela um pouco. Adicionar ou subtrair (conforme apropriado) a propriedade `size` do círculo maligno faria sentido.

#### `setControls()`

Esse método adicionará um ouvinte de evento `onkeydown` ao objeto `window` para que, quando determinadas teclas do teclado forem pressionadas, possamos mover o círculo maligno ao redor. O bloco de código a seguir deve ser colocado dentro da definição do método:

```js
var _this = this;
window.onkeydown = function (e) {
  if (e.keyCode === 65) {
    _this.x -= _this.velX;
  } else if (e.keyCode === 68) {
    _this.x += _this.velX;
  } else if (e.keyCode === 87) {
    _this.y -= _this.velY;
  } else if (e.keyCode === 83) {
    _this.y += _this.velY;
  }
};
```

Assim, quando uma tecla é pressionada, a propriedade keyCode (en-US) é consultada para ver qual tecla é pressionada. Se for um dos quatro representados pelos códigos de teclas especificados, o círculo maligno se moverá para a esquerda / direita / para cima / para baixo.

* Para um ponto de bônus, deixe-nos saber a quais chaves os códigos de teclas específicos estão mapeados.
* Para outro ponto de bônus, você pode nos dizer por que precisamos definir `var _this = this;` na posição em que está? É algo a ver com o escopo da função.

#### `collisionDetect()`

Este método irá agir de forma muito semelhante ao método `collisionDetect()` do `Ball()`, então você pode usar uma cópia disso como base deste novo método. Mas há algumas diferenças:

* Na declaração `if` externa, você não precisa mais verificar se a bola atual na iteração é igual à bola que está fazendo a verificação - porque ela não é mais uma bola, é o círculo do mal! Em vez disso, você precisa fazer um teste para ver se a bola que está sendo checada existe (com qual propriedade você poderia fazer isso?). Se não existe, já foi comido pelo círculo do mal, por isso não há necessidade de verificá-lo novamente.
* Na instrução `if` interna, você não quer mais que os objetos mudem de cor quando uma colisão é detectada — em vez disso, você quer definir quaisquer bolas que colidam com o círculo maligno para não existir mais (novamente, como você pensa? d fazer isso?).
### Trazendo o círculo do mal para o programa

Agora nós definimos o círculo do mal, precisamos realmente fazer isso aparecer em nossa cena. Para fazer isso, você precisa fazer algumas alterações na função `loop()`.

* Primeiro de tudo, crie uma nova instância de objeto do círculo do mal (especificando os parâmetros necessários) e, em seguida, chame seu método `setControls()`. Você só precisa fazer essas duas coisas uma vez, não em todas as iterações do loop.
* No ponto em que você percorre todas as bolas e chama as funções `draw()`, `update()`, e `collisionDetect()` para cada uma, faça com que essas funções sejam chamadas apenas se a bola atual existir.
* Chame os métodos `draw()`, `checkBounds()`, e `collisionDetect()` da instância do mal ball em cada iteração do loop.
### Implementando o contador de pontuação

Para implementar o contador de pontuação, siga os seguintes passos:

1. No seu arquivo HTML, adicione um elemento `<p>` logo abaixo do elemento `<h1>` (en-US) contendo o texto "Contagem de bolas:".
2. No seu arquivo CSS, adicione a seguinte regra na parte inferior:

```css
p {
  position: absolute;
  margin: 0;
  top: 35px;
  right: 5px;
  color: #aaa;
}
```

3. Em seu JavaScript, faça as seguintes atualizações:
    * Crie uma variável que armazene uma referência ao parágrafo.
    * Mantenha uma contagem do número de bolas na tela de alguma forma.
    * Incrementar a contagem e exibir o número atualizado de bolas cada vez que uma bola é adicionada à cena.
    * Decrementar a contagem e exibir o número atualizado de bolas cada vez que o círculo maligno come uma bola (faz com que ele não exista).
Dicas e sugestões
-----------------

* Essa avaliação é bastante desafiadora. Tome cada passo devagar e com cuidado.
* Pode ser uma idéia manter uma cópia separada da demo depois que você fizer com que cada estágio funcione, para que você possa consultá-la caso se encontre em apuros mais tarde.
Avaliação
---------

Se você está seguindo esta avaliação como parte de um curso organizado, você deve poder dar seu trabalho ao seu professor / mentor para marcação. Se você é auto-didata, então você pode obter o guia de marcação com bastante facilidade, perguntando no tópico de discussão para este exercício, ou no canal de #mdn IRC da Mozilla IRC. Tente o exercício primeiro — não há nada a ganhar com a trapaça!

* Anterior
* Menu: Objects


Herança em JavaScript - Aprendendo desenvolvimento web

Herança em JavaScript
=====================

* Anterior
* Menu: Objects
* Próxima

Com a maior parte dos detalhes principais do OOJS agora explicados, este artigo mostra como criar classes de objetos "child" (construtores) que herdam recursos de suas classes "parent". Além disso, apresentamos alguns conselhos sobre quando e onde você pode usar o OOJS e veja como as classes são tratadas na sintaxe moderna do ECMAScript.

|  |  |
| --- | --- |
| Pré-requisitos: |
 Conhecimento básico de computação, conhecimento básico de HTML e CSS,
 familiaridade com com o básico de Javascript (veja
 Primeiros passos
 e
 Construindo blocos) e OOJS básico (veja
 Introdução a objetos (en-US)).
  |
| Objetivo: | Entender como é possível implementar a herança em Javascript. |

Herança Prototipada
-------------------

Até agora vimos alguma herança em ação — vimos como funcionam as cadeias de protótipos e como os membros são herdados subindo em uma cadeia. Mas principalmente isso envolveu funções internas do navegador. Como criamos um objeto em JavaScript que herda de outro objeto?

Vamos explorar como fazer isso com um exemplo concreto.

Começando
---------

Primeiro de tudo, faça uma cópia local do arquivo oojs-class-inheritance-start.html (veja também ao vivo). Aqui dentro você encontrará o mesmo exemplo de construtor `Person()` que utilizamos durante todo o módulo, com uma pequena diferença — definimos apenas as propriedades dentro do construtor:

```js
function Person(first, last, age, gender, interests) {
  this.name = {
    first,
    last,
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
}
```

Os métodos são *todos* definidos no protótipo do construtor. Por exemplo:

```js
Person.prototype.greeting = function () {
  alert("Hi! I'm " + this.name.first + ".");
};
```

**Nota:** No código fonte, você também verá os métodos `bio()` e `farewell()` definidos. Depois você verá como eles podem ser herdados por outros construtores.

Digamos que quiséssemos criar uma classe `Teacher`, como a que descrevemos em nossa definição inicial orientada a objetos, que herda todos os membros de `Person`, mas também inclui:

1. Uma nova propriedade, `subject` — isso irá conter o assunto que o professor ensina.
2. Um método `greeting()` atualizado, que soa um pouco mais formal do que o método padrão `greeting()` — mais adequado para um professor que se dirige a alguns alunos da escola.
Definindo uma função construtora Teacher()
------------------------------------------

A primeira coisa que precisamos fazer é criar um construtor `Teacher()` — adicione o seguinte abaixo do código existente:

```js
function Teacher(first, last, age, gender, interests, subject) {
  Person.call(this, first, last, age, gender, interests);

  this.subject = subject;
}
```

Isto parece similar ao construtor Person de várias maneiras, mas há algo estranho aqui que nós não vimos antes — a função `call()`. Esta função basicamente permite chamar uma função definida em outro lugar, mas no contexto atual. O primeiro parâmetro especifica o valor `this` que você deseja usar ao executar a função, e os outros parâmetros são aqueles que devem ser passados para a função quando ela é invocada.

Nós queremos que o construtor `Teacher()` pegue os mesmos parâmetros que o construtor `Person()` de onde ele está herdando, então especificamos todos eles como parâmetros na chamada `call()`.

A última linha dentro do construtor simplesmente define a nova propriedade `subject` que os professores terão, que pessoas genéricas não possuem.

Como nota, poderíamos simplesmente ter feito isso:

```js
function Teacher(first, last, age, gender, interests, subject) {
  this.name = {
    first,
    last,
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
  this.subject = subject;
}
```

Mas isso é apenas redefinir as propriedades de novo, não herdá-las de `Person()`, de modo que ela derrota o ponto que estamos tentando fazer. Também leva mais linhas de código.

### Herdando de um construtor sem parâmetros

Observe que, se o construtor do qual você está herdando não tomar seus valores de propriedade de parâmetros, não será necessário especificá-los como argumentos adicionais em `call()`. Então, por exemplo, se você tivesse algo realmente simples assim:

```js
function Brick() {
  this.width = 10;
  this.height = 20;
}
```

Você pode herdar as propriedades `width` e `height` fazendo isso (assim como as outras etapas descritas abaixo, é claro):

```js
function BlueGlassBrick() {
  Brick.call(this);

  this.opacity = 0.5;
  this.color = "blue";
}
```

Observe que apenas especificamos `this` dentro de `call()` — nenhum outro parâmetro é necessário, já que não estamos herdando propriedades do pai que são configuradas por meio de parâmetros.

Definindo o protótipo e referência de construtor do Teacher()
-------------------------------------------------------------

Tudo está bem até agora, mas nós temos um problema. Nós definimos um novo construtor, e ele tem uma propriedade `prototype`, que por padrão apenas contém uma referência à própria função construtora. Ele não contém os métodos da propriedade `prototype` do construtor Person. Para ver isso, insira `Object.getOwnPropertyNames(Teacher.prototype)` no campo de entrada de texto ou no seu console JavaScript. Em seguida, insira-o novamente, substituindo `Teacher` por `Person`. O novo construtor também não herda esses métodos. Para ver isso, compare as saídas de `Person.prototype.greeting` e `Teacher.prototype.greeting`. Precisamos obter `Teacher()` para herdar os métodos definidos no protótipo `Person()`. Então, como fazemos isso?

1. Adicione a seguinte linha abaixo da sua adição anterior:

```js
Teacher.prototype = Object.create(Person.prototype);
```

Aqui nosso amigo `create()` vem para o resgate novamente. Nesse caso, estamos usando para criar um novo objeto e torná-lo o valor de `Teacher.prototype`. O novo objeto tem `Person.prototype` como seu protótipo e, portanto, herdará, se e quando necessário, todos os métodos disponíveis no `Person.prototype`.
2. Precisamos fazer mais uma coisa antes de prosseguirmos. Depois de adicionar a última linha, a propriedade `constructor` de `Teacher.prototype` agora é igual a `Person()`, porque apenas definimos `Teacher.prototype` para fazer referência a um objeto que herda suas propriedades de `Person.prototype`! Tente salvar seu código, carregar a página em um navegador e inserir `Teacher.prototype.constructor` no console para verificar.
3. Isso pode se tornar um problema, então precisamos definir isso corretamente. Você pode fazer isso voltando ao seu código-fonte e adicionando a seguinte linha na parte inferior:

```js
Object.defineProperty(Teacher.prototype, "constructor", {
  value: Teacher,
  enumerable: false, // so that it does not appear in 'for in' loop
  writable: true,
});
```

4. Agora, se você salvar e atualizar, entrar em `Teacher.prototype.constructor` deve retornar `Teacher()`, conforme desejado, além de estarmos herdando de `Person()`!
Dar a Teacher() uma nova função greeting()
------------------------------------------

Para finalizar nosso código, precisamos definir uma nova função `greeting()` no construtor `Teacher()`.

A maneira mais fácil de fazer isso é defini-lo no protótipo do `Teacher()` — adicione o seguinte na parte inferior do seu código:

```js
Teacher.prototype.greeting = function () {
  var prefix;

  if (
    this.gender === "male" ||
    this.gender === "Male" ||
    this.gender === "m" ||
    this.gender === "M"
  ) {
    prefix = "Mr.";
  } else if (
    this.gender === "female" ||
    this.gender === "Female" ||
    this.gender === "f" ||
    this.gender === "F"
  ) {
    prefix = "Mrs.";
  } else {
    prefix = "Mx.";
  }

  alert(
    "Hello. My name is " +
      prefix +
      " " +
      this.name.last +
      ", and I teach " +
      this.subject +
      ".",
  );
};
```

Isso alerta a saudação do professor, que também usa um prefixo de nome apropriado para seu gênero, elaborado usando uma instrução condicional.

Testando o exemplo
------------------

Agora que você digitou todo o código, tente criar uma instância de objeto do `Teacher()` colocando o seguinte na parte inferior do seu JavaScript (ou algo semelhante à sua escolha):

```js
var teacher1 = new Teacher(
  "Dave",
  "Griffiths",
  31,
  "male",
  ["football", "cookery"],
  "mathematics",
);
```

Agora salve e atualize e tente acessar as propriedades e os métodos do novo objeto `teacher1`, por exemplo:

```js
teacher1.name.first;
teacher1.interests[0];
teacher1.bio();
teacher1.subject;
teacher1.greeting();
teacher1.farewell();
```

Tudo isso deve funcionar bem. As consultas nas linhas 1, 2, 3 e 6 acessam membros herdados do construtor genérico `Person()` (class). A consulta na linha 4 acessa um membro que está disponível somente no construtor mais especializado `Teacher()` (class). A consulta na linha 5 teria acessado um membro herdado de `Person()`, exceto pelo fato de que `Teacher()` tem seu próprio membro com o mesmo nome, portanto, a consulta acessa esse membro.

**Nota:** If you have trouble getting this to work, compare your code to our finished version (see it running live also).

A técnica que abordamos aqui não é a única maneira de criar classes herdadas em JavaScript, mas funciona bem e dá uma boa idéia sobre como implementar a herança em JavaScript.

Você também pode estar interessado em conferir alguns dos novos recursos ECMAScript (en-US) que nos permitem fazer herança mais claramente em JavaScript (veja Classes). Nós não cobrimos esses aqui, pois eles ainda não são suportados amplamente pelos navegadores. Todas as outras construções de código que discutimos neste conjunto de artigos são suportadas desde o IE9 ou anterior, e existem maneiras de obter suporte anterior a isso.

Uma maneira comum é usar uma biblioteca JavaScript — a maioria das opções populares tem um conjunto fácil de funcionalidade disponível para fazer herança com mais facilidade e rapidez. CoffeeScript por exemplo, fornece `class`, `extends`, etc.

Um exercício adicional
----------------------

Em nossa seção de teoria OOP, incluímos também uma classe `Student` como um conceito, que herda todos os recursos de `Person`, e também tem um método `greeting()` diferente de `Person` que é muito mais informal do que a saudação do `Teacher`. Dê uma olhada na aparência da saudação do aluno nessa seção e tente implementar seu próprio construtor `Student()` que herda todos os recursos de `Person()`, e implemente a função `greeting()` diferente.

**Nota:** If you have trouble getting this to work, have a look at our finished version (see it running live also).

Sumário de membro do objeto
---------------------------

Resumindo, você basicamente tem três tipos de propriedade / método para se preocupar:

1. Aqueles definidos dentro de uma função construtora que são dadas a instâncias de objetos. Estes são bastante fáceis de detectar — em seu próprio código personalizado, eles são os membros definidos dentro de um construtor usando as linhas `this.x = x` ; no código do navegador, eles são os membros disponíveis apenas para instâncias de objetos (geralmente criados chamando um construtor usando a palavra-chave `new`, por exemplo, `var myInstance = new myConstructor()`).
2. Aqueles definidos diretamente no próprio construtor, que estão disponíveis apenas no construtor. Geralmente, eles estão disponíveis apenas em objetos de navegador internos e são reconhecidos por serem encadeados diretamente em um construtor, não em uma instância. Por exemplo, `Object.keys()`.
3. Aqueles definidos no protótipo de um construtor, que são herdados por todas as instâncias e herdam as classes de objetos. Estes incluem qualquer membro definido na propriedade de protótipo de um Construtor, por ex. `myConstructor.prototype.x()`.

Se você não tem certeza de qual é qual, não se preocupe com isso ainda — você ainda está aprendendo e a familiaridade virá com a prática.

Classes ECMAScript 2015
-----------------------

O ECMAScript 2015 introduz a sintaxe de classe em JavaScript como uma maneira de escrever classes reutilizáveis usando uma sintaxe mais fácil e mais limpa, que é mais semelhante a classes em C ++ ou Java. Nesta seção, converteremos os exemplos Pessoa e Professor da herança protótipo para as classes, para mostrar como é feito.

**Nota:** Essa forma moderna de escrever classes é suportada em todos os navegadores modernos, mas ainda vale a pena saber como a herança prototípica subjacente, caso você trabalhe em um projeto que exija suporte a um navegador que não suporte essa sintaxe (mais notavelmente o Internet Explorer) .

Vejamos uma versão reescrita do exemplo Person, estilo de classe:

```js
class Person {
  constructor(first, last, age, gender, interests) {
    this.name = {
      first,
      last,
    };
    this.age = age;
    this.gender = gender;
    this.interests = interests;
  }

  greeting() {
    console.log(`Hi! I'm ${this.name.first}`);
  }

  farewell() {
    console.log(`${this.name.first} has left the building. Bye for now!`);
  }
}
```

A declaração class indica que estamos criando uma nova classe. Dentro deste bloco, definimos todos os recursos da classe:

* O método `constructor()` define a função construtora que representa nossa classe `Person`.
* `greeting()` e `farewell()` são métodos de classe. Quaisquer métodos que você deseja associar à classe são definidos dentro dela, após o construtor. Neste exemplo, usamos template literals em vez de concatenação de string para facilitar a leitura do código.

Agora podemos instanciar instâncias de objeto usando o operador `new`, da mesma maneira que fizemos antes:

```js
let han = new Person("Han", "Solo", 25, "male", ["Smuggling"]);
han.greeting();
// Hi! I'm Han

let leia = new Person("Leia", "Organa", 19, "female", ["Government"]);
leia.farewell();
// Leia has left the building. Bye for now
```

**Nota:** Sob o capô, suas classes estão sendo convertidas em modelos de herança protótipos — isso é apenas açúcar sintático. Mas tenho certeza que você concordará que é mais fácil escrever.

### Herança com sintaxe de classe

Acima nós criamos uma classe para representar uma pessoa. Eles têm uma série de atributos que são comuns a todas as pessoas; Nesta seção, criaremos nossa classe especializada `Teacher`, tornando-a herdada de `Person` usando a sintaxe de classe moderna. Isso é chamado de criação de uma subclasse ou subclasse.

Para criar uma subclasse, usamos a palavra-chave extends para informar ao JavaScript a classe na qual queremos basear nossa classe.

```js
class Teacher extends Person {
  constructor(first, last, age, gender, interests, subject, grade) {
    this.name = {
      first,
      last,
    };

    this.age = age;
    this.gender = gender;
    this.interests = interests;
    // subject and grade are specific to Teacher
    this.subject = subject;
    this.grade = grade;
  }
}
```

Podemos tornar o código mais legível definindo o operador `super()` como o primeiro item dentro do `constructor()`. Isso chamará o construtor da classe pai e herdará os membros que especificarmos como parâmetros de `super()`, desde que sejam definidos lá:

```js
class Teacher extends Person {
  constructor(first, last, age, gender, interests, subject, grade) {
    super(first, last, age, gender, interests);

    // subject and grade are specific to Teacher
    this.subject = subject;
    this.grade = grade;
  }
}
```

Quando instanciamos instâncias de objeto `Teacher` , podemos agora chamar métodos e propriedades definidos em `Teacher` e `Person`, como seria de esperar:

```js
let snape = new Teacher(
  "Severus",
  "Snape",
  58,
  "male",
  ["Potions"],
  "Dark arts",
  5,
);
snape.greeting(); // Hi! I'm Severus.
snape.farewell(); // Severus has left the building. Bye for now.
snape.age; // 58
snape.subject; // Dark arts
```

Como fizemos com Teachers, poderíamos criar outras subclasses de `Person` para torná-las mais especializadas sem modificar a classe base.

**Nota:** You can find this example on GitHub as es2015-class-inheritance.html (see it live also).

Getters e Setters
-----------------

Pode haver momentos em que queremos alterar os valores de um atributo nas classes que criamos ou não sabemos qual será o valor final de um atributo. Usando o exemplo `Teacher`, podemos não saber o assunto que o professor ensinará antes de criá-lo, ou o assunto pode mudar entre os termos.

Podemos lidar com essas situações com getters e setters.

Vamos melhorar a classe Professor com getters e setters. A aula começa da mesma forma que foi a última vez que olhamos para ela.

Os getters e setters trabalham em pares. Um getter retorna o valor atual da variável e seu setter correspondente altera o valor da variável para o que ela define.

A classe `Teacher` modificada é assim:

```js
class Teacher extends Person {
  constructor(first, last, age, gender, interests, subject, grade) {
    super(first, last, age, gender, interests);
    // subject and grade are specific to Teacher
    this._subject = subject;
    this.grade = grade;
  }

  get subject() {
    return this._subject;
  }

  set subject(newSubject) {
    this._subject = newSubject;
  }
}
```

Em nossa classe acima, temos um getter e setter para a propriedade `subject`. Usamos **`_`** para criar um valor separado no qual armazenar nossa propriedade de nome. Sem usar essa convenção, obteríamos erros toda vez que chamássemos get ou set. Neste ponto:

* Para mostrar o valor atual da propriedade `_subject` do objeto `snape` , podemos usar o método getter `snape.subject`.
* Para atribuir um novo valor à propriedade `_subject` , podemos usar o método setter `snape.subject="new value"`.

O exemplo abaixo mostra os dois recursos em ação:

```js
// Check the default value
console.log(snape.subject); // Returns "Dark arts"

// Change the value
snape.subject = "Balloon animals"; // Sets \_subject to "Balloon animals"

// Check it again and see if it matches the new value
console.log(snape.subject); // Returns "Balloon animals"
```

**Nota:** You can find this example on GitHub as es2015-getters-setters.html (see it live also).

Quando você usaria a herança em JavaScript?
-------------------------------------------

Particularmente após este último artigo, você pode estar pensando "woo, isso é complicado". Bem, você está certo. Protótipos e herança representam alguns dos aspectos mais complexos do JavaScript, mas muito do poder e flexibilidade do JavaScript vem de sua estrutura e herança de objetos, e vale a pena entender como ele funciona.

De certa forma, você usa herança o tempo todo. Sempre que você usa vários recursos de uma API da Web ou métodos / propriedades definidos em um objeto de navegador interno que você chama em suas cadeias de caracteres, matrizes, etc., você está implicitamente usando herança.

Em termos de usar a herança em seu próprio código, você provavelmente não a usará com frequência, principalmente no começo e em pequenos projetos. É uma perda de tempo usar objetos e herança apenas por causa dela quando você não precisa deles. Mas à medida que suas bases de código aumentam, é mais provável que você encontre uma necessidade para isso. Se você estiver começando a criar vários objetos com recursos semelhantes, criar um tipo de objeto genérico para conter toda a funcionalidade compartilhada e herdar esses recursos em tipos de objetos mais especializados pode ser conveniente e útil.

**Nota:** Por causa da maneira como o JavaScript funciona, com a cadeia de protótipos, etc., o compartilhamento de funcionalidade entre objetos é frequentemente chamado de **delegação**. Os objetos especializados delegam a funcionalidade a um tipo de objeto genérico.

Ao usar a herança, você é aconselhado a não ter muitos níveis de herança, e manter um controle cuidadoso de onde você define seus métodos e propriedades. É possível começar a escrever código que modifica temporariamente os protótipos dos objetos do navegador interno, mas você não deve fazer isso a menos que tenha um bom motivo. Demasiada herança pode levar a confusão sem fim, e dor infinita quando você tenta depurar esse código.

Em última análise, os objetos são apenas outra forma de reutilização de código, como funções ou loops, com seus próprios papéis e vantagens específicos. Se você estiver criando um monte de variáveis e funções relacionadas e quiser rastreá-las todas juntas e empacotá-las perfeitamente, um objeto é uma boa ideia. Objetos também são muito úteis quando você quer passar uma coleção de dados de um lugar para outro. Ambas as coisas podem ser alcançadas sem o uso de construtores ou herança. Se você precisa apenas de uma única instância de um objeto, provavelmente é melhor usar apenas um literal de objeto e certamente não precisa de herança.

Alternativas para estender a cadeia de protótipos
-------------------------------------------------

Em JavaScript, existem várias maneiras diferentes de estender o protótipo de um objeto além do que mostramos acima. Para saber mais sobre as outras formas, visite nosso artigo Herança e a cadeia de protótipos.

Sumário
-------

Este artigo cobriu o restante da teoria e sintaxe central do OOJS que achamos que você deveria saber agora. Neste ponto, você deve entender os princípios de objeto e OOP JavaScript, protótipos e herança prototypal, como criar classes (construtores) e instâncias de objetos, adicionar recursos a classes e criar subclasses que herdam de outras classes.

No próximo artigo, veremos como trabalhar com JavaScript Object Notation (JSON), um formato comum de troca de dados escrito usando objetos JavaScript.

Veja também
-----------

* ObjectPlayground.com — Um site de aprendizado interativo realmente útil para aprender sobre objetos.
* Segredos Ninja de JavaScript, Capítulo 7 - Um bom livro sobre conceitos e técnicas avançadas de JavaScript, por John Resig, Bear Bibeault e Josip Maras. O Capítulo 7 aborda aspectos de protótipos e herança muito bem; Você provavelmente pode rastrear uma cópia impressa ou on-line com bastante facilidade.
* Você não sabe JS: this & Object Prototypes — Parte da excelente série de manuais de JavaScript de Kyle Simpson, o Capítulo 5, em particular, analisa os protótipos com muito mais detalhes do que fazemos aqui. Nós apresentamos uma visão simplificada nesta série de artigos destinados a iniciantes, enquanto Kyle entra em grande profundidade e fornece uma imagem mais complexa, mas mais precisa.
* Anterior
* Menu: Objects
* Próxima


Prática de construção de objetos - Aprendendo desenvolvimento web

Prática de construção de objetos
================================

* Anterior
* Menu: Objects
* Próxima

Nos artigos anteriores, analisamos todos os detalhes essenciais da teoria e da sintaxe do objeto JavaScript, fornecendo uma base sólida para começar. Neste artigo, vamos mergulhar em um exercício prático, dando a você mais prática na construção de objetos JavaScript personalizados, com um resultado divertido e colorido.

|  |  |
| --- | --- |
| Pré-requisitos: |
 Conhecimentos básicos de informática, conhecimento básico de HTML e CSS,
 familiaridade com o básico de JavaScript (veja
 First steps e
 Building blocks) e o básico de OOJS (veja
 Introduction to objects (en-US)).
  |
| Objetivo: |
 Adiquirir alguma prática no uso de objetos e técnicas de orientação a
 objetos num contexto real.
  |

Vamos saltitar algumas bolas
----------------------------

Neste artigo, vamos escrever uma demo clássica de "bolas saltitantes", para mostrar o quão úteis os objetos podem ser em JavaScript. Nossas bolinhas vão saltar pela tela e mudam de cor quando se tocam. O exemplo acabado vai parecer um pouco assim:
 ![](/pt-BR/docs/Learn/JavaScript/Objects/Object_building_practice/bouncing-balls.png)

Este exemplo fará uso da Canvas API (en-US), para desenhar as bolas na tela, e da requestAnimationFrame API para animar toda a exibição — você não precisa ter nenhum conhecimento prévio dessas APIs e esperamos que, no momento em que você terminar este artigo, você esteja interessado em explorá-los mais. Ao longo do caminho, faremos uso de alguns objetos bacanas, e mostraremos algumas técnicas legais, como bolas quicando nas paredes, e verificando se elas se chocaram (também conhecidas como **detecção de colisão**).

Começando
---------

Para começar, faça cópias locais de nossos arquivos `index.html`, `style.css`, e `main.js`. Estes contêm o seguinte, respectivamente:

1. Um documento HTML muito simples com um elemento `<h1>` (en-US), um elemento `<canvas>` para desenhar nossas bolas e elementos para aplicar nosso CSS e JavaScript em nosso HTML.
2. Alguns estilos muito simples, que servem principalmente para estilizar e posicionar o `<h1>`, e se livrar de qualquer barra de rolagem ou margem ao redor da borda da página (para que fique bonito e arrumado).
3. Algum JavaScript que serve para configurar o elemento `<canvas>` e fornecer uma função geral que vamos usar.

A primeira parte do script é assim:

```js
const canvas = document.querySelector("canvas");

const ctx = canvas.getContext("2d");

const width = (canvas.width = window.innerWidth);
const height = (canvas.height = window.innerHeight);
```

Esse script obtém uma referência ao elemento `<canvas>` e, em seguida, chama o método `getContext()` para nos fornecer um contexto no qual podemos começar a desenhar. A variável resultante (`ctx`) é o objeto que representa diretamente a área de desenho da tela e nos permite desenhar formas 2D nela.

Em seguida, definimos variáveis chamadas `width` e `height`, e a largura e altura do elemento canvas (representado pelas propriedades `canvas.width` e `canvas.height`) para igualar a largura e a altura da viewport do navegador (a área em que a página da Web aparece — isso pode ser obtido das propriedades `Window.innerWidth` (en-US) e `Window.innerHeight` ).

Você verá aqui que estamos encadeando várias tarefas juntas, para que as variáveis sejam todas mais rápidas — isso é perfeitamente aceitável.

A última parte do script inicial é a seguinte:

```js
function random(min, max) {
  const num = Math.floor(Math.random() \* (max - min + 1)) + min;
  return num;
}
```

Essa função usa dois números como argumentos e retorna um número aleatório no intervalo entre os dois.

Modelando uma bola no nosso programa
------------------------------------

Nosso programa contará com muitas bolas saltando ao redor da tela. Como todas essas bolas se comportarão da mesma maneira, faz sentido representá-las com um objeto. Vamos começar adicionando o construtor a seguir ao final do código.

```js
function Ball(x, y, velX, velY, color, size) {
  this.x = x;
  this.y = y;
  this.velX = velX;
  this.velY = velY;
  this.color = color;
  this.size = size;
}
```

Aqui incluímos alguns parâmetros que definem as propriedades que cada bola precisa para funcionar em nosso programa:

* coordenadas `x` e `y` — coordenadas horizontal e vertical onde a bola vai começar na tela. Isso pode variar entre 0 (canto superior esquerdo) à largura e altura da janela de visualização do navegador (canto inferior direito).
* velocidade horizontal e vertical (`velX` e `velY`) — cada bola recebe uma velocidade horizontal e vertical; em termos reais, esses valores serão adicionados regularmente aos valores das coordenadas `x`/`y` quando começarmos a animar as bolas, para movê-las tanto em cada quadro.
* `color` — cada bola recebe uma cor.
* `size` — cada bola recebe um tamanho — este será o seu raio, em pixels.

Isso classifica as propriedades, mas e os métodos? Queremos realmente fazer com que nossas bolas façam algo em nosso programa.

### Desenhando a bola

Primeiro adicione o seguinte método `draw()` ao `prototype` do `Ball()`:

```js
Ball.prototype.draw = function () {
  ctx.beginPath();
  ctx.fillStyle = this.color;
  ctx.arc(this.x, this.y, this.size, 0, 2 \* Math.PI);
  ctx.fill();
};
```

Usando esta função, podemos dizer a nossa bola para desenhar-se na tela, chamando uma série de membros do contexto de tela 2D que definimos anteriormente (`ctx`). O contexto é como o papel, e agora queremos comandar nossa caneta para desenhar algo nela:

* Primeiro, usamos `beginPath()` para declarar que queremos desenhar uma forma no papel.
* Em seguida, usamos `fillStyle` para definir a cor que queremos que a forma seja — nós a definimos como a propriedade `color` da nossa bola.
* Em seguida, usamos o método `arc()` para traçar uma forma de arco no papel. Seus parâmetros são:
    + A posição `x` e `y` do centro do arco — estamos especificando as propriedades `x` e `y` da nossa bola.
    + O raio do nosso arco — estamos especificando a propriedade `size` da nossa bola.
    + Os dois últimos parâmetros especificam o número inicial e final de graus em volta do círculo em que o arco é desenhado entre eles. Aqui nós especificamos 0 graus e `2 * PI`, que é o equivalente a 360 graus em radianos (irritantemente, você tem que especificar isso em radianos). Isso nos dá um círculo completo. Se você tivesse especificado apenas `1 * PI`, você obteria um semicírculo (180 graus).
* Por último, usamos o método `fill()`, que basicamente diz "terminar de desenhar o caminho que começamos com `beginPath()`, e preencher a área que ocupa com a cor que especificamos anteriormente em `fillStyle`."

Você pode começar a testar seu objeto já.

1. Salve o código até o momento e carregue o arquivo HTML em um navegador.
2. Abra o console JavaScript do navegador e, em seguida, atualize a página para que o tamanho da tela mude para a viewport menor visível deixada quando o console for aberto.
3. Digite o seguinte para criar uma nova instância de bola:

```js
let testBall = new Ball(50, 100, 4, 4, "blue", 10);
```

4. Tente chamar seus membros:

```js
testBall.x;
testBall.size;
testBall.color;
testBall.draw();
```

5. Quando você entra na última linha, você deve ver a bola se desenhando em algum lugar na sua tela.
### Atualizando os dados da bola

Podemos desenhar a bola na posição, mas para começar a mover a bola, precisamos de uma função de atualização de algum tipo. Adicione o seguinte código na parte inferior do seu arquivo JavaScript, para adicionar um método `update()` ao `prototype` do `Ball()`:

```js
Ball.prototype.update = function () {
  if (this.x + this.size >= width) {
    this.velX = -this.velX;
  }

  if (this.x - this.size <= 0) {
    this.velX = -this.velX;
  }

  if (this.y + this.size >= height) {
    this.velY = -this.velY;
  }

  if (this.y - this.size <= 0) {
    this.velY = -this.velY;
  }

  this.x += this.velX;
  this.y += this.velY;
};
```

As primeiras quatro partes da função verificam se a bola atingiu a borda da tela. Se tiver, invertemos a polaridade da velocidade relevante para fazer a bola viajar na direção oposta. Assim, por exemplo, se a bola estava viajando para cima (positivo `velY`), então a velocidade vertical é alterada de forma que ela comece a viajar para baixo (negativo `velY`).

Nos quatro casos, estamos verificando se:

* Se a coordenada `x` é maior que a largura da tela (a bola está saindo da borda direita).
* Se a coordenada `x` é menor que 0 (a bola está saindo da borda esquerda).
* Se a coordenada `y` é maior que a altura da tela (a bola está saindo da borda inferior).
* Se a coordenada `y` é menor que 0 (a bola está saindo da borda superior).

Em cada caso, estamos incluindo o `size` da bola no cálculo, porque as coordenadas `x`/`y` estão no centro da bola, mas queremos que a borda da bola saia do perímetro — não queremos a bola para fique no meio da tela antes de quicar de volta.

As duas últimas linhas adicionam o valor `velX` à coordenada `x`, e o valor `velY` à coordenada `y` — a bola é efitivamente movida cada vez que este método é chamado.

Isso é o que será feito por ora; vamos continuar com alguma animação!

Animando a bola
---------------

Agora vamos tornar isso divertido. Vamos começar a adicionar bolas à tela e a animá-las.

1. Primeiro, precisamos de criar um lugar para armazenar todas as nossas bolas e então preenche-lo. O código a seguir fará esse trabalho — adicione-o ao final do seu código agora:

```js
let balls = [];

while (balls.length < 25) {
  let size = random(10, 20);
  let ball = new Ball(
    // ball position always drawn at least one ball width
    // away from the edge of the canvas, to avoid drawing errors
    random(0 + size, width - size),
    random(0 + size, height - size),
    random(-7, 7),
    random(-7, 7),
    "rgb(" +
      random(0, 255) +
      "," +
      random(0, 255) +
      "," +
      random(0, 255) +
      ")",
    size,
  );

  balls.push(ball);
}
```

O laço `while` cria uma nova instância da nossa `Ball()` usando valores aleatórios gerados com nossa função `random()`, então a função `push()` coloca ela no final do nosso array de bolas, mas somente enquanto o número de bolas no array é menor que 25. Então quando nos tivermos 25 bolas na tela mais nenhuma bola aparece. Você pode tentar variar o número em `balls.length < 25` para obter mais ou menos bolas na tela. Dependendo de quanto poder de processamento seu computador/navegador tiver, especificar várias milhares de bolas pode diminuir bastante a velocidade da animação!
2. Adicione o seguinte ao final do seu código agora:

```js
function loop() {
  ctx.fillStyle = "rgba(0, 0, 0, 0.25)";
  ctx.fillRect(0, 0, width, height);

  for (let i = 0; i < balls.length; i++) {
    balls[i].draw();
    balls[i].update();
  }

  requestAnimationFrame(loop);
}
```

Todos os programas que animam as coisas geralmente envolvem um loop de animação, que serve para atualizar as informações no programa e renderizar a visualização resultante em cada quadro da animação; esta é a base para a maioria dos jogos e outros programas. Nossa função `loop()` faz o seguinte:
    * Define a cor de preenchimento da tela como preto semitransparente e desenha um retângulo com a cor em toda a largura e altura da tela, usando `fillRect()` (os quatro parâmetros fornecem uma coordenada de início e uma largura e altura para o retângulo desenhado ). Isso serve para encobrir o desenho do quadro anterior antes que o próximo seja desenhado. Se você não fizer isso, você verá apenas longas cobras se movimentando ao redor da tela, em vez de mover as bolas! A cor do preenchimento é definida como semitransparente, `rgba(0,0,0,0.25)`, para permitir que os poucos quadros anteriores brilhem levemente, produzindo as pequenas trilhas atrás das bolas à medida que elas se movem. Se você mudou 0,25 para 1, você não vai mais vê-los. Tente variar esse número para ver o efeito que ele tem.
    * Percorre todas as bolas no array `balls` e executa a função `draw()` e `update()` de cada bola para desenhar cada uma delas na tela, depois faz as atualizações necessárias para a posição e a velocidade a tempo para o próximo quadro.
    * Executa a função novamente usando o método `requestAnimationFrame()` — quando esse método é executado constantemente e passa o mesmo nome de função, ele executará essa função um número definido de vezes por segundo para criar uma animação suave. Isso geralmente é feito de forma recursiva — o que significa que a função está chamando a si mesma toda vez que é executada, portanto, ela será executada repetidas vezes.
3. Por último mas não menos importante, adicione a seguinte linha à parte inferior do seu código — precisamos chamar a função uma vez para iniciar a animação.

```js
loop();
```

É isso para o básico — tente salvar e atualizar para testar suas bolas quicando!

Adicionando detecção de colisão
-------------------------------

Agora, para um pouco de diversão, vamos adicionar alguma detecção de colisão ao nosso programa, para que nossas bolas saibam quando bateram em outra bola.

1. Primeiro de tudo, adicione a seguinte definição de método abaixo onde você definiu o método `update()` (ou seja, o bloco `Ball.prototype.update`).

```js
Ball.prototype.collisionDetect = function () {
  for (let j = 0; j < balls.length; j++) {
    if (!(this === balls[j])) {
      const dx = this.x - balls[j].x;
      const dy = this.y - balls[j].y;
      const distance = Math.sqrt(dx \* dx + dy \* dy);

      if (distance < this.size + balls[j].size) {
        balls[j].color = this.color =
          "rgb(" +
          random(0, 255) +
          "," +
          random(0, 255) +
          "," +
          random(0, 255) +
          ")";
      }
    }
  }
};
```

Esse método é um pouco complexo, então não se preocupe se você não entender exatamente como isso funciona agora. Uma explicação a seguir:
    * Para cada bola, precisamos checar todas as outras bolas para ver se ela colidiu com a bola atual. Para fazer isso, abrimos outro loop `for` para percorrer todas as bolas no array `balls[]`.
    * Imediatamente dentro de nosso loop for, usamos uma instrução `if` para verificar se a bola atual em loop é a mesma bola que estamos verificando no momento. Não queremos verificar se uma bola colidiu consigo mesma! Para fazer isso, verificamos se a bola atual (ou seja, a bola cujo método collisionDetect está sendo invocado) é a mesma que a bola de loop (ou seja, a bola que está sendo referenciada pela iteração atual do loop for no collisionDetect método). Nós então usamos `!` para negar a verificação, para que o código dentro da instrução if seja executado apenas se eles não forem iguais.
    * Em seguida, usamos um algoritmo comum para verificar a colisão de dois círculos. Estamos basicamente verificando se alguma das áreas dos dois círculos se sobrepõe. Isso é explicado ainda mais na 2D collision detection.
    * Se uma colisão for detectada, o código dentro da instrução `if` interna será executado. Neste caso, estamos apenas definindo a propriedade `color` de ambos os círculos para uma nova cor aleatória. Poderíamos ter feito algo muito mais complexo, como fazer com que as bolas saltassem umas das outras de forma realista, mas isso teria sido muito mais complexo de implementar. Para essas simulações físicas, os desenvolvedores tendem a usar jogos ou bibliotecas físicas, como PhysicsJS, matter.js, Phaser, etc.
2. Você também precisa chamar esse método em cada quadro da animação. Adicione o seguinte abaixo do `balls[i].update();`:

```js
balls[i].collisionDetect();
```

3. Salve e atualize a demonstração novamente, e você verá suas bolas mudando de cor quando colidirem!

**Nota:** If you have trouble getting this example to work, try comparing your JavaScript code against our finished version (also see it running live).

Sumário
-------

Esperamos que você tenha se divertido escrevendo seu próprio exemplo de bolas saltitantes aleatórias do mundo real, usando várias técnicas orientadas a objetos e objetos de todo o módulo! Isso deve ter lhe dado alguma prática útil no uso de objetos e um bom contexto do mundo real.

É isso para artigos de objetos — tudo o que resta agora é para você testar suas habilidades na avaliação de objetos.

Veja também
-----------

* Canvas tutorial — um guia para iniciantes sobre o uso de telas (canvas) 2D .
* requestAnimationFrame()
* 2D collision detection
* 3D collision detection (en-US)
* 2D breakout game using pure JavaScript (en-US) — um ótimo tutorial para iniciantes que mostra como criar um jogo 2D.
* 2D breakout game using Phaser (en-US) — explica conceitos básicos da criação de um jogo 2D utilizando uma biblioteca JavaScript.
* Anterior
* Menu: Objects
* Próxima


Matemática básica no JavaScript — números e operadores - Aprendendo desenvolvimento web

Matemática básica no JavaScript — números e operadores
======================================================

* Anterior
* Menu: First steps
* Próxima

Neste ponto do curso estaremos discutindo matemática em JavaScript — Como podemos usar operadores e outros recursos para manipular números e fazer cálculos.

|  |  |
| --- | --- |
| Pré-requisitos: |
 Conhecimento básico em informática, uma compreensão básica de HTML e
 CSS, uma compreensão do que é o JavaScript.
  |
| Objetivo: | Ganhar familiaridade com o básico em matemática no JavaScript. |

Todo mundo ama matemática
-------------------------

Ok, talvez não. Alguns de nós gostam de matemática, alguns de nós tem a odiado desde que tivemos que aprender a tabuada de multiplicação e divisão na escola, e alguns de nós estão em algum lugar no meio dos dois cenários. Mas nenhum de nós pode negar que a matemática é uma parte fundamental da vida sem a qual não poderíamos ir muito longe. Isso é especialmente verdadeiro quando estamos aprendendo a programar em JavaScript (ou em qualquer outra linguagem, diga-se de passagem) — muito do que fazemos se baseia no processamento de dados numéricos, cálculo de novos valores, etc. Assim você não ficará surpreso em aprender que o JavaScript tem uma configuração completa de funções matemáticas disponíveis.

Este artigo discute apenas as partes básicas que você precisa saber agora.

### Tipos de números

Em programação, até mesmo o humilde sistema de números decimais que todos nós conhecemos tão bem é mais complicado do que você possa pensar. Usamos diferentes termos para descrever diferentes tipos de números decimais, por exemplo:

* **Integers** (inteiros) são números inteiros, ex. 10, 400 ou -5.
* **Números de ponto flutuante** *(floats)* tem pontos e casas decimais, por exemplo 12.5 e 56.7786543.
* **Doubles** são tipos de *floats* que tem uma precisão maior do que os números de ponto flutuante padrões (significando que eles são mais precisos, possuindo uma grande quantidade de casas decimais).

Temos até mesmo diferentes tipos de sistemas numéricos! O decimal tem por base 10 (o que significa que ele usa um número entre 0–9 em cada casa), mas temos também algo como:

* **Binário** — A linguagem de menor level dos computadores; 0s e 1s.
* **Octal** — Base 8, usa um caractere entre 0–7 em cada coluna.
* **Hexadecimal** — Base 16, usa um caractere entre 0–9 e depois um entre a–f em cada coluna. Você pode já ter encontrado esses números anteriormente, trabalhando com cores no CSS.

**Antes de se preocupar com seu cérebro estar derretendo, pare agora mesmo!** Para um começo, vamos nos ater aos números decimais no decorrer desse curso; você raramente irá se deparar com a necessidade de começar a pensar sobre os outros tipos, se é que vai precisar algum dia.

A segunda boa notícia é que, diferentemente de outras linguagens de programação, o JavaScript tem apenas um tipo de dados para números, você advinhou, `Number`. Isso significa que qualquer que seja o tipo de números com os quais você está lidando em JavaScript, você os manipula do mesmo jeito.

### Tudo é número para mim

Vamos brincar rapidamente com alguns números para nos familiarizarmos com a sintaxe básica que precisamos. Insira os comandos listados abaixo em seu console JavaScript, ou use o console simples incorporado abaixo, se preferir.

**Abra em uma nova janela**

1. Primeiramente, vamos declarar duas variáveis e as inicializar com um *integer* e um *float*, respectivamente, então digitaremos os nomes das variáveis para verificar se está tudo em ordem:

```js
var meuInt = 5;
var meuFloat = 6.667;
meuInt;
meuFloat;
```

2. Valores numéricos são inseridos sem aspas — tente declarar e inicializar mais duas variáveis contendo números antes de seguir em frente.
3. Agora vamos checar se nossas duas variáveis originais são do mesmo tipo de dados. Há um operador chamado `typeof` no JavaScript que faz isso. Insira as duas linhas conforme mostradas abaixo:

```js
typeof meuInt;
typeof meuFloat;
```

Você deve obter `"number"` de volta nos dois casos — isso torna as coisas muito mais fáceis para nós do que se diferentes tipos de números tivessem diferentes tipos de dados, e tivéssemos que lidar com eles em diferentes maneiras. Ufa!
Operadores aritméticos
----------------------

São os operadores que utilizamos para fazer as operações aritiméticas básicas:

| Operador | Nome | Propósito | Exemplo |
| --- | --- | --- | --- |
| `+` | Adição | Adiciona um número a outro. | `6 + 9` |
| `-` | Subtração | Subtrai o número da direita do número da esquerda. | `20 - 15` |
| `*` | Multiplicação | Multiplica um número pelo outro. | `3 * 7` |
| `/` | Divisão | Divide o número da esquerda pelo número da direita. | `10 / 5` |
| `%` | Restante *(Remainder* - as vezes chamado de modulo) | Retorna o resto da divisão em números inteiros do número da esquerda pelo número da direita. | `8 % 3` (retorna 2; como três cabe duas vezes em 8, deixando 2 como resto.) |

**Nota:** Você verá algumas vezes números envolvidos em aritimética chamados de operandos.

Nós provavelmente não precisamos ensinar a você como fazer matemática básica, mas gostaríamos de testar seu entendimento da sintaxe envolvida. Tente inserir os exemplos abaixo no seu console JavaScript, ou use o console incorporado visto anteriormente, se preferir, para familiarizar-se com a sintaxe.

1. Primeiro tente inserir alguns exemplos simples por sua conta, como

```js
10 + 7;
9 \* 8;
60 % 3;
```

2. Você pode tentar declarar e inicializar alguns números dentro de variáveis, e tentar usá-los nas operações — as variáveis irão se comportar exatamente como os valores que elas armazenam para a finalidade das operações. Por exemplo:

```js
var num1 = 10;
var num2 = 50;
9 \* num1;
num2 / num1;
```

3. Por último, nesta seção, tente inserir algumas expressões mais complexas, como:

```js
5 + 10 \* 3;
(num2 % 9) \* num1;
num2 + num1 / 8 + 2;
```

Alguns dos exemplos do último bloco podem não ter retornado os valores que você estava esperando; a seção abaixo pode lhe explicar o porquê.

### Precedência de operador

Vamos olhar para o último exemplo, assumindo que `num2` guarda o valor 50 e `num1` possui o valor 10 (como iniciado acima):

```js
num2 + num1 / 8 + 2;
```

Como um ser humano, talvez você leia isso como *"50 mais 10 é igual a 60"*, depois *"8 mais 2 é igual a 10"*, e então *"60 dividido por 10 é igual a 6"*.

No entanto seu navegador vai ler *"10 dividido por 8 é igual a 1.25"*, então *"50 mais 1.25 mais 2 é igual a 53.25"*.

Isto acontence por causa da **precedência de operadores** — algumas operações serão aplicadas antes de outras quando calcularmos o resultado de uma soma (referida em programação como uma expressão). A precedência de operadores em JavaScript é semelhante ao ensinado nas aulas de matemática na escola — Multiplicação e divisão são realizados primeiro, depois a adição e subtração (a soma é sempre realizada da esquerda para a direita).

Se você quiser substituir a precedência do operador, poderá colocar parênteses em volta das partes que desejar serem explicitamente tratadas primeiro. Então, para obter um resultado de 6, poderíamos fazer isso:

```js
(num2 + num1) / (8 + 2);
```

Tente fazer e veja como fica.

**Nota:** Uma lista completa de todos os operadores JavaScript e suas precedências pode ser vista em Expressões e operadores.

Operadores de incremento e decremento
-------------------------------------

Às vezes você desejará adicionar ou subtrair, repetidamente, um valor de uma variável numérica. Convenientemente isto pode ser feito usando os operadores incremento `++` e decremento `--`. Usamos `++` em nosso jogo "Adivinhe o número" no primeiro artigo Um primeiro mergulho no JavaScript, quando adicionamos 1 ao nosso `contagemPalpites` para saber quantas adivinhações o usuário deixou após cada turno.

```js
contagemPalpites++;
```

**Nota:** Eles são mais comumente usado em Laços e iterações, que será visto no curso mais tarde. Por exemplo, digamos que você queira passar por uma lista de preços e adicionar imposto sobre vendas a cada um deles. Você usaria um loop para passar por cada valor e fazer o cálculo necessário para adicionar o imposto sobre vendas em cada caso. O incrementador é usado para mover para o próximo valor quando necessário. Na verdade, fornecemos um exemplo simples mostrando como isso é feito - verifique ao vivo e observe o código-fonte para ver se consegue identificar os incrementadores! Veremos os *loops* detalhadamente mais adiante no curso.

Vamos tentar brincar com eles no seu console. Para começar, note que você não pode aplicá-las diretamente a um número, o que pode parecer estranho, mas estamos atribuindo a variável um novo valor atualizado, não operando no próprio valor. O seguinte retornará um erro:

```js
3++;
```

Então, você só pode incrementar uma variável existente. Tente isto:

```js
var num1 = 4;
num1++;
```

Ok, segunda coisa estranha! Quando você fizer isso, verá um valor 4 retornado - isso ocorre porque o navegador retorna o valor atual e, *em seguida*, incrementa a variável. Você pode ver que ele foi incrementado se você retornar o valor da variável novamente:

```js
num1;
```

Acontece a mesma coisa com `--` : tente o seguinte

```js
var num2 = 6;
num2--;
num2;
```

**Nota:** Você pode fazer o navegador fazer o contrário - incrementar/decrementar a variável e depois retornar o valor, colocando o operador no início da variável ao invés do final. Tente os exemplos acima novamente, mas desta vez use `++num1` e `--num2`.

Operadores de atribuição
------------------------

Operadores de atribuição são os que atribuem um valor à uma variável. Nós já usamos o básico, `=`, muitas vezes, simplesmente atribuindo à variável do lado esquerdo o valor indicado do lado direito do operador:

```js
var x = 3; // x contém o valor 3
var y = 4; // y contém o valor 4
x = y; // x agora contém o mesmo valor de y, 4
```

Mas existem alguns tipos mais complexos, que fornecem atalhos úteis para manter seu código mais puro e mais eficiente. Os mais comuns estão listados abaixo:

| Operator | Name | Purpose | Example | Shortcut for |
| --- | --- | --- | --- | --- |
| `+=` | Atribuição de adição | Adiciona o valor à direita ao valor da variável à esquerda e, em seguida, retorna o novo valor da variável | `x = 3; x += 4;` | `x = 3; x = x + 4;` |
| `-=` | Atribuição de subtração | Subtrai o valor à direita do valor da variável à esquerda e retorna o novo valor da variável | `x = 6; x -= 3;` | `x = 6; x = x - 3;` |
| `*=` | Atribuição de multiplicação | Multiplica o valor da variável à esquerda pelo valor à direita e retorna o novo valor da variável | `x = 2; x *= 3;` | `x = 2; x = x * 3;` |
| `/=` | Atribuição de divisão | Divide o valor da variável à esquerda pelo valor à direita e retorna o novo valor da variável | `x = 10; x /= 5;` | `x = 10; x = x / 5;` |

Tente digitar alguns dos exemplos acima em seu console para ter uma ideia de como eles funcionam. Em cada caso, veja se você pode adivinhar qual é o valor antes de digitar a segunda linha.

Note que você pode muito bem usar outros valores no lado direito de cada expressão, por exemplo:

```js
var x = 3; // x contém o valor 3
var y = 4; // y contém o valor 4
x \*= y; // x agora contém o valor 12
```

**Nota:** Existem muitos outros operadores de atribuição disponíveis, mas estes são os básicos que você deve aprender agora.

Aprendizado ativo: dimensionando uma canvas box
-----------------------------------------------

Neste exercício, você manipulará alguns números e operadores para alterar o tamanho de uma caixa. A caixa é desenhada usando uma API do navegador chamada Canvas API. Não há necessidade de se preocupar sobre como isso funciona, apenas concentre-se na matemática por enquanto. A largura e altura da caixa (em pixels) são definidas pelas variáveis x e y, que recebem um valor inicial de 50.

**Abrir em nova janela**

Na caixa de código editável acima, há duas linhas marcadas com um comentário que gostaríamos que você atualizasse para aumentar/diminuir a caixa para determinados tamanhos, usando determinados operadores e/ou valores em cada caso. Vamos tentar o seguinte:

* Altere a linha que calcula x para que a caixa ainda tenha 50px de largura, mas que 50 seja calculado usando os números 43 e 7 e um operador aritmético.
* Altere a linha que calcula y tenha 75px de altura, mas que 75 seja calculado usando os números 25 e 3 e um operador aritmético.
* Altere a linha que calcula x para que a caixa tenha 250px de largura, mas que 250 seja calculado usando dois números e o operador resto (modulo).
* Altere a linha que calcula y para que a caixa tenha 150px de altura, mas que 150 seja calculado usando três números e os operadores de subtração e divisão.
* Altere a linha que calcula x para que a caixa tenha 200px de largura, mas que 200 seja calculado usando o número 4 e um operador de atribuição.
* Altere a linha que calcula y para que a caixa tenha 200px de altura, mas que 200 seja calculado usando os números 50 e 3, o operador de multiplicação e o operador de atribuição de adição.

Não se preocupe se você estragar totalmente o código. Você sempre pode pressionar o botão Reset para fazer as coisas funcionarem novamente. Depois de ter respondido corretamente a todas as perguntas acima, sinta-se à vontade para brincar um pouco com o código ou crie seus próprios desafios.

Operadores de comparação
------------------------

Às vezes, queremos executar testes verdadeiro / falso e, em seguida, agir de acordo, dependendo do resultado desse teste, para fazer isso, usamos **operadores de comparação**.

| Operator | Name | Purpose | Example |
| --- | --- | --- | --- |
| `===` | Igualdade estrita | Verifica se o valor da esquerda e o da direita são idênticos entre si. | `5 === 2 + 4` |
| `!==` | Não-igualdade-estrita | Verifica se o valor da esquerda e o da direita **não** são idênticos entre si. | `5 !== 2 + 3` |
| `<` | Menor que | Verifica se o valor da esquerda é menor que o valor da direita. | `10 < 6` |
| `>` | Maior que | Verifica se o valor da esquerda é maior que o valor da direita. | `10 > 20` |
| <= | Menor ou igual que | Verifica se o valor da esquerda é menor que ou igual ao valor da direita. | `3 <= 2` |
| >= | Maior ou igual que | Verifica se o valor da esquerda é maior que ou igual ao valor da direita. | `5 >= 4` |

**Nota:** Talvez você já tenha visto alguém usando `==` e`!=` afim de testar igualdade ou desigualdade em JavaScript. Estes são operadores válidos em JavaScript, mas que diferem de `===`/`!==`. As versões anteriores testam se os valores são os mesmos, mas não se os tipos de dados dos valores são os mesmos. As últimas versões estritas testam a igualdade de ambos os valores e seus tipos de dados. Elas tendem a resultar em menos erros, por isso recomendamos que você as use.

Se você tentar inserir alguns desses valores em um console, verá que todos eles retornam `true`/`false` — aqueles booleanos que mencionamos no último artigo. Eles são muito úteis, pois nos permitem tomar decisões em nosso código, e eles são usados toda vez que queremos fazer uma escolha de algum tipo. Por exemplo, booleanos podem ser usados para:

* Exibir o text label em um botão, dependendo se um recurso está ativado ou desativado
* Exibir uma mensagem de 'game over' se um jogo acabou ou uma mensagem de vitória se o jogo foi vencido
* Exibir uma saudação sazonal correta, dependendo da época de festas
* Aumentar ou diminuir o zoom do mapa, dependendo do nível de zoom selecionado

Veremos como codificar essa lógica quando examinarmos instruções condicionais em um artigo futuro. Por enquanto, vamos dar uma olhada em um exemplo rápido:

```html
<button>Iniciar máquina</button>
<p>A máquina está parada.</p>
```

```js
var btn = document.querySelector("button");
var txt = document.querySelector("p");

btn.addEventListener("click", updateBtn);

function updateBtn() {
  if (btn.textContent === "Iniciar máquina") {
    btn.textContent = "Parar máquina";
    txt.textContent = "A máquina iniciou!";
  } else {
    btn.textContent = "Iniciar máquina";
    txt.textContent = "A máquina está parada.";
  }
}
```

**Abrir em nova janela**

Você pode ver o operador de igualdade sendo usado apenas dentro da função `updateBtn()`. Neste caso, não estamos testando se duas expressões matemáticas têm o mesmo valor, estamos testando se o conteúdo de texto de um botão contém uma certa string , mas ainda é o mesmo princípio em funcionamento. Se o botão estiver dizendo "Iniciar máquina" quando for pressionado, mudaremos o rótulo para "Parar máquina" e atualizaremos o rótulo conforme apropriado. Se o botão estiver dizendo "Parar máquina" quando for pressionado, nós trocamos a tela de volta.

**Nota:** Esse controle que troca entre dois estados geralmente é chamado de **toggle**. Ele alterna entre um estado e outro - acender, apagar, etc.

Resumo
------

Neste artigo, cobrimos as informações fundamentais que você precisa saber sobre números em JavaScript, por enquanto. Você verá os números sendo usados de novo e de novo, durante todo o aprendizado de JavaScript. Portanto, é uma boa ideia tirar isso do caminho agora. Se você é uma daquelas pessoas que não gosta de matemática, pode se consolar com o fato de este capítulo ser muito curto.

No próximo artigo, vamos explorar o texto e como o JavaScript nos permite manipulá-lo.

**Nota:** Se você gosta de matemática e quer saber mais sobre como ela é implementada em JavaScriot, você pode encontrar muito mais detalhes na seção principal de JavaScript do MDN. Ótimos lugares para começar são os artigos Números e datas e Expressões e operadores .

* Anterior
* Menu: First steps
* Próxima


O que deu errado? Resolvendo problemas no JavaScript - Aprendendo desenvolvimento web

O que deu errado? Resolvendo problemas no JavaScript
====================================================

* Anterior
* Menu: First steps
* Próxima

Quando você construiu o jogo "Adivinhe o número" no artigo anterior, você talvez tenha descoberto que ele não funcionou. Não tema — este artigo tem como objetivo impedir que você arranque os cabelos por causa desses problemas, fornecendo-lhe algumas dicas simples de como encontrar e corrigir erros nos programas JavaScript.

|  |  |
| --- | --- |
| Pré-requesitos: |
 Conhecimentos básicos de informática, uma compreensão básica de HTML e
 CSS, uma compreensão do que é JavaScript.
  |
| Objetivo: |
 Ganhar habilidade e confiança para começar a resolver problemas simples
 em seu próprio código.
  |

Tipos de erros
--------------

De um modo geral, quando você faz algo errado no código, existem dois tipos principais de erros que você encontrará:

* **Erros de sintaxe:** são erros de ortografia em seu código que realmente fazem com que o programa não seja executado, ou pare de trabalhar parcialmente - você geralmente receberá algumas mensagens de erro também. Estes geralmente são adequados para consertar, desde que você esteja familiarizado com as ferramentas certas e saiba o que as mensagens de erro significam!
* **Erros lógicos:** são erros onde a sintaxe está realmente correta, mas o código não é o que você pretendia, o que significa que o programa é executado com sucesso, mas dá resultados incorretos. Muitas vezes, eles são mais difíceis de consertar do que erros de sintaxe, pois geralmente não há uma mensagem de erro resultante para direcioná-lo para a origem do erro.

Ok, então não é assim tão simples - há alguns outros diferenciadores à medida que você aprofunda. Mas as classificações acima serão bem úteis nesta fase inicial da sua carreira. Examinaremos esses dois tipos a seguir.

Um exemplo errôneo
------------------

Para começar, voltemos ao nosso jogo de adivinhação - porém desta vez estaremos explorando uma versão que tem alguns erros inseridos propositalmente. Vá até o Github e faça uma cópia local de jogo-numero-erros.html (veja-o em execução aqui).

1. Para começar, abra a cópia local dentro do seu editor de texto favorito, e em seu navegador.
2. Tente jogar o jogo - você notará que, quando você pressiona o botão "Enviar palpite", ele não funciona!

>
> \*\*Nota:\*\*Talvez você tenha sua própria versão de exemplo do jogo que não funciona, e pode querer consertá-la! Nós ainda gostaríamos que você trabalhasse no artigo com a nossa versão, para que possa aprender as técnicas que estamos ensinando aqui. Daí então você pode voltar e tentar consertar seu exemplo.
>
>
>

Neste ponto, vamos consultar o console do desenvolvedor para ver se identificamos qualquer erro de sintaxe, e então tentar consertá-lo. Você irá aprender como, logo abaixo.

Consertando erros de sintaxe
----------------------------

Anteriormente no curso, nós fizemos você digitar alguns comandos simples de JavaScript no console JavaScript (se você não se lembra como, abra o link anterior). O que é ainda mais útil é o fato do console lhe mostrar mensagens de erro sempre que existir algo errado na sintaxe dentro do JavaScript enviado ao motor de JavaScript do navegador. Agora vamos à caça.

1. Vá até a aba onde você tem aberto o arquivo `jogo-numero-erros.html` e abra o console JavaScript. Você deverá ver uma mensagem de erro sendo exibida:

 ![](/pt-BR/docs/Learn/JavaScript/First_steps/What_went_wrong/nao-e-uma-funcao.png)
2. Esse é um erro bem fácil de identifcar, e o navegador lhe fornece várias informações úteis para lhe ajudar (a captura de tela acima foi feita no Firefox, mas os outros navegadores oferecem informações similares). Da esquerda para a direita, nós temos:
    * Um "x" laranja para indicar que esse é um erro.
    * Uma mensagem de erro para indicar o que está errado: "TypeError: envioPalpite.addeventListener is not a function"
    * Um link "Learn More" que encaminha à uma página no MDN docs explicando o que esse erro significa em uma quantidade enorme de detalhes.
    * O nome do arquivo JavaScript, que direciona à aba Debugger das ferramentas de desenvolvimento. Se você clicar nesse link, verá a linha exata onde o erro está destatacada.
    * O número da linha onde o erro se encontra, e o número do caractere na linha onde o erro é encontrado primeiro. Neste caso nós temos, linha 86, caractere número 3.
3. Se olharmos para a linha 86 em nosso nosso código de código, vamos encontrar a seguinte linha:

```js
envioPalpite.addeventListener('click', conferir Palpite);
```

4. O erro diz o seguinte "envioPalpite.addeventListener is not a function", que significa envioPalpite.addeventListener não é uma funçao. Então provavelmente digitamos algo errado. Se você não estiver certo da digitação correta de parte da sintaxe, é uma boa ideia procurar a funcionalidade no MDN docs. A melhor forma de fazer isso atualmente é pesquisar por "mdn *nome-da-funcionalidade*" em seu mecanismo de buscas favorito. Aqui está um atalho para te salvar algum tempo nesse caso: `addEventListener()`.
5. Então, olhando nessa essa página, o erro parece ser termos digitado o nome da função errado! Lembre-se de que o JavaScript diferencia letras maiúsculas de minúsculas, então qualquer diferença na digitação ou no uso de letras maiúsculas irá causar um erro. Alterar `addeventListener` para `addEventListener` deverá corrigir esse erro. Faça essa alteração no código do seu arquivo.

**Nota:** Veja nossa página de referência TypeError: "x" is not a function para mais detalhes sobre esse erro.

### Erros de sintaxe - segundo round

1. Salve o arquivo e atualize a aba do navegador, e você poderá ver que o erro foi corrigido.
2. Agora se você tentar enviar um palpite e pressionar o botão !Enviar palpite" você verá... outro erro!

 ![](/pt-BR/docs/Learn/JavaScript/First_steps/What_went_wrong/variavel-e-nula.png)
3. Dessa vez o erro informado é "TypeError: baixoOuAlto is null", na linha 78.

**Nota:** `Null` é um valor especial que significa "nada", ou "sem valor". Então `baixoOuAlto` foi declarado e inicializado, mas não com algum valor significativo — não possui nenhum caractere ou valor.

**Nota:** Esse erro não apareceu assim que a página foi carregada porque esse erro ocorreu dentro de uma função (dentro do bloco `conferirPalpite() { ... }` ). Como você irá aprender com mais detalhes no nosso artigo de funções mais tarde, o código localizado dentro de funções roda em um escopo separado do código presente fora das funções. Nesse caso, o código não estava rodando e o erro não estava aparecendo até a função `conferirPalpite()` ser executada na linha 86.
4. Dê uma olhada na linha 78, e você verá o seguinte código:

```js
baixoOuAlto.textContent = "Seu palpite foi muito alto!";
```

5. Essa linha está tentando definir a propriedade `textContent` (conteúdo de texto) da variável `baixoOuAlto` como uma sequência de texto, mas isso não está funcionando porque `baixoOuAlto` não contém o que deveria conter. Vamos ver o porquê — tente localizar outras instâncias de `baixoOuAlto` no código. A instância que aparece primeiro no código JavaScript é na linha 48:

```js
var baixoOuAlto = document.querySelector("baixoOuAlto");
```

6. Nesse ponto estamos tentando fazer com que a variável contenha uma referência a um elemento no documento HTML. Vamos conferir se o valor é `null` (nulo) depois que essa linha é executada. Adicione o seguinte código na linha 49:

```js
console.log(baixoOuAlto);
```

**Nota:** `console.log()` é uma função de debugging (correção de erros) realmente útil que exibe um valor na tela do console. Então ela irá imprimir o valor da variável `baixoOuAlto` na tela do console assim que tentarmos defini-la na linha 48.
7. Salve o arquivo e o atualize no navegador, e você deverá ver agora o resultado do `console.log()` na tela do seu console.

 ![](/pt-BR/docs/Learn/JavaScript/First_steps/What_went_wrong/console-log-saida.png)
 Pois bem, nesse ponto o valor de `baixoOuAlto` e `null`, então definitivamente há um problema com a linha 48.
8. Vamos pensar em qual poderia ser o problema. A linha 48 está usando um método `document.querySelector()` para pegar a referência do elemento selecionado com um seletor CSS selector (*CSS selector*). Olhando mais acima no nosso código, podemos encontrar o parágrafo em questão:

```js
<p class="baixoOuAlto"></p>
```

9. Então nós precisamos de um seletor de classe aqui, que começa com um ponto (.), mas o seletor passado pelo método `querySelector()` na linha 48 não tem o ponto. Esse pode ser o problema! Tente mudar `baixoOuAlto` para `.baixoOuAlto` na linha 48.
10. Tente salvar o arquivo e atualizá-lo no navegador de novo, e a sua declaração `console.log()` deverá retornar o elemento `<p>` que queremos. Ufa! Outro erro resolvido! Você pode deletar a linha do seu `console.log()` agora, ou mantê-la para referência posterior — a escolha é sua.

**Nota:** Veja nossa página de referência TypeError: "x" is (not) "y" para mais detalhes sobre esse erro.

### Erros de sintaxe - terceiro round

1. Agora se você tentar jogar novamente, você deve ter mais sucesso — o jogo deve continuar normalmente, até você terminar, ou adivinhando o número, ou ficando sem mais chances.
2. Nesse ponto, o jogo falha mais uma vez, e o mesmo erro do início é exibido — "TypeError: botaoReinicio.addeventListener is not a function"! No entanto, dessa vez é listado vindo da linha 94.
3. Olhando a linha 94, é fácil de ver que nós cometemos o mesmo erro novamente. Só precisamos alterar mais uma vez `addeventListener` para `addEventListener`. Faça isso.
Um erro de lógica
-----------------

Nesse ponto, o jogo deve rodar normalmente, porém depois de jogá-lo algumas vezes você irá notar que o número "aleatório" que você tem que adivinhar é sempre igual a 1. Definitivamente não é como queremos que o jogo funcione!

Há sem dúvida um problema na lógica do jogo em algum lugar — o jogo não está retornando nenhum erro; simplesmente não está funcionando corretamente.

1. Procure pela variável `numeroAleatorio`, e as linhas onde o número aleatório é definido primeiro. A instância que armazena o número aleatório que queremos adivinhar no começo do jogo deve estar na linha 44 ou próximo a ela:

```js
var numeroAleatorio = Math.floor(Math.random()) + 1;
```

2. E a linha que gera o número aleatório antes de cada jogo subsequente está na linha 113, ou próximo a ela:

```js
numeroAleatorio = Math.floor(Math.random()) + 1;
```

3. Para checar se essas linhas são mesmo o problema, vamos recorrer ao nosso amigo `console.log()` de novo — insira a seguinte linha diretamente abaixo de cada uma das duas linhas:

```js
console.log(numeroAleatorio);
```

4. Salve o arquivo e atualize o navegador, então jogue algumas vezes — você verá que o `numeroAleatorio` é igual a 1 cada vez em que é exibido no console.
### Trabalhando através da lógica

Para consertar isso, vamos considerar como essa linha está trabalhando. Primeiro, nós invocamos `Math.random()`, que gera um número decimal aleatório entre 0 e 1, ex. 0.5675493843.

```js
Math.random();
```

Em seguida, passamos o resultado invocando `Math.random()` através de `Math.floor()`, que arredonda o número passado para o menor número inteiro mais próximo. E então adicionamos 1 ao resultado:
```

Math.floor(Math.random()) + 1
```

Arredondando um número decimal aleatório entre 0 e 1 para baixo irá sempre retornar 0, então adicionando 1 a ele sempre retornará 1. Precisamos multiplicar o número aleatório por 100 antes de o arredondarmos para baixo. O código seguinte nos daria um número aleatório entre 0 and 99:

```js
Math.floor(Math.random() \* 100);
```

Por isso, queremos adicionar 1, para nos dar um número aleatório entre 1 e 100:

```js
Math.floor(Math.random() \* 100) + 1;
```

Tente atualizar as duas linhas dessa forma, então salve e atualize o navegador — o jogo deve agora funcionar como nós queremos que funcione!

Outros erros comuns
-------------------

Existem outros erros comuns com os quais você irá esbarrar em seu código. Essa seção destaca a maioria deles.

### *SyntaxError: missing ; before statement*

Erro de sintaxe: faltando ";" antes da declaração. Esse erro geralmente significa que você deixou de inserir um ponto e vírgula ao final de uma de suas linhas de código, mas algumas vezes pode ser mais crítico. Por exemplo, se mudarmos essa linha (número 58) dentro da função `conferirPalpite()`:

```js
var palpiteUsuario = Number(campoPalpite.value);
```

para

```js
var palpiteUsuario === Number(campoPalpite.value);
```

Exibe esse erro porque pensa que você está fazendo algo diferente. Você deve se certificar de não misturar o operador de atribuição (`=`) — que configura uma variável para ser igual a determinado valor — com o operador de igualdade restrita (`===`), que testa se um valor é exatamente igual a outro, e retorna um resultado `true`/`false` (verdadeiro ou falso).

**Nota:** Veja nossa página de referência SyntaxError: missing ; before statement (en-US) para mais detalhes sobre esse erro.

### O programa sempre diz que você ganhou, independentemente do palpite que insira

Isso pode ser outro sintoma de confusão entre o operador de atribuição e o operador de igualdade restrita. Por exemplo, se nós quiséssemos essa linha dentro de `conferirPalpite()`:

```js
if (palpiteUsuario === numeroAleatorio) {
```

para

```js
if (palpiteUsuario = numeroAleatorio) {
```

o teste retornaria sempre `true` (verdadeiro), causando o programa a reportar que o jogo foi vencido. Tome cuidado!

### *SyntaxError: missing ) after argument list*

Erro de sintaxe: faltando ")" depois de listar uma declaração. Esse é bem simples — geralmente significa que deixamos de fechar o parênteses no final ao invocar uma função/método.

**Nota:** Veja nossa página de referência SyntaxError: missing ) after argument list para mais detalhes sobre o erro.

### *SyntaxError: missing : after property id*

Erro de sintaxe: faltando ":" depois da propriedade id. Esse erro geralmente se relaciona à formação incorreta de um objeto de JavaScript, mas nesse caso o obtivemos alterando:

```js
function conferirPalpite() {
```

para

```js
function conferirPalpite( {
```

Isso levou o navegador a pensar que estávamos tentando passar todo o conteúdo da função como se fosse um argumento dessa função. Seja cuidadoso com esses parênteses!

### *SyntaxError: missing } after function body*

Erro de sintaxe: faltando "}" depois do corpo da função. Isso é fácil — geralmente significa que você deixou de colocar uma das chaves de uma função ou de uma estrutura condicional. Nós obtemos esse erro deletando uma das chaves de fechamento próximas ao final da função `conferirPalpite()`.

### *SyntaxError: expected expression, got 'string'* ou *SyntaxError: unterminated string literal*

Erro de sintaxe: esperado uma expressão, obtido uma 'string' e Erro de sintaxe: string literal não terminada. Esses erros geralmente significam que você deixou de colocar aspas no início ou no final da declaração de uma cadeia de texto. No primeiro erro acima, '*string'* seria substituído pelo(s) caractere(s) encontrado(s) pelo navegador ao invés da aspa no início de uma cadeia de texto. O segundo erro quer dizer que a cadeia de texto não foi finalizada com o caractere de aspa.

Para todos esses erros, pense em como nós abordamos os exemplos em que olhamos no passo a passo. Quando um erro surge, olha o número da linha que é informado, vá até essa linha e veja se consegue localizar o que há de errado. Mantenha em mente que o erro não estará necessariamente nessa linha, e também que o erro pode não ter sido causado exatamente pelo mesmo problema que citamos acima!

**Nota:** Veja nossas páginas de referência SyntaxError: Unexpected token e SyntaxError: unterminated string literal para mais detalhes sobre esses erros.

Sumário
-------

Então aqui temos, o básico de como resolver erros em programas simples de JavaScript. Não será sempre tão fácil de solucionar o que está errado em seu código, mas pelo menos isso irá te poupar algumas horas de sono e lhe permitir progredir um pouco mais rápido quando as coisas não saírem certas no início da sua jornada de aprendizado.

Veja também
-----------

* Há muitos outros tipos de erros que não listamos aqui; estamos compilando uma referência que explica o que eles significam em detalhes — veja a referência de erros do JavaScript.
* Se você se deparar com qualquer erro em seu código que não tenha certeza de como resolver mesmo depois de ler este artigo, você pode pedir ajuda! Pergunte na Área de Discussão e Aprendizagem, ou no canal IRC #mdn em Mozilla IRC. Nos diga quel é o seu erro, e nós iremos tentar te ajudar. Uma amostra do seu código também seria útil.
* Anterior
* Menu: First steps
* Próxima


Gerador de histórias bobas - Aprendendo desenvolvimento web

Gerador de histórias bobas
==========================

* Anterior
* Menu: First steps

Nesta avaliação, você será encarregado de utilizar parte do conhecimento que você adquiriu nos artigos deste módulo e aplicá-lo para criar um aplicativo divertido que gera histórias bobas aleatórias. Divirta-se!

|  |  |
| --- | --- |
| Pré-requisitos: |
 Antes de tentar esta avaliação, você já deve ter trabalhado com todos os
 artigos deste módulo.
  |
| Objetivo: |
 Testar a compreensão dos fundamentos de JavaScript, como variáveis,
 números, operadores, cadeias de caracteres e matrizes.
  |

Ponto de partida
----------------

Para começar esta avaliação, você deve:

* Pegue o arquivo HTML para o exemplo e salve uma cópia local deste arquivo como index.html em um novo diretório em algum local do seu computador. Este arquivo ainda contém o CSS para estilizar o exemplo contido no arquivo.
* Vá para a página que contém o texto bruto e matenha-a aberta em uma aba separada do navegador em algum lugar. Você precisará dela mais tarde.

**Nota:** Alternativamente, você pode utilizar um site como JSBin ou Thimble para fazer a sua avaliação. Você pode colar o HTML, CSS e javaScript em um desses editores online. Se o editor online que você estiver utilizando não possuir um painel separado para javaScript, sinta-se a vontade para inseri-lo em um elemento <script> dentro da página HTML.

Resumo do projeto
-----------------

Você recebeu algum HTML/CSS em bruto e algumas strings de texto e funções de JavaScript; Você precisa escrever o JavaScript necessário para transformar este em um programa funcional, que faz o seguinte:

* Gera uma história boba quando o botão "Gerar história aleatória" é pressionado.
* Substitui o nome padrão "Bob" na história com um nome personalizado, somente se um nome personalizado for inserido no campo de texto "Inserir nome personalizado" antes que o botão de geração seja pressionado.
* Gera outra história boba aleatória se você pressionar novamente o botão (e novamente...)

A seguinte captura de tela mostra um exemplo do que o programa concluído deve produzir:

![](/pt-BR/docs/Learn/JavaScript/First_steps/Silly_story_generator/assessment-1.png)

Para dar-lhe mais uma ideia, dê uma olhada no exemplo concluído (sem espreitar o código fonte!)

Passos para completar
---------------------

As seções a seguir descrevem o que você precisa fazer.

Configuração básica:

1. Crie um novo arquivo chamado main.js, no mesmo diretório que o arquivo index.html.
2. Aplique o arquivo JavaScript externo ao seu HTML inserindo um elemento `<script>` no seu HTML referenciando o main.js. Coloque-o antes da etiqueta de fechamento `<body>`.

Variáveis e funções iniciais:

1. No arquivo de texto cru, copie todo o código abaixo do cabeçalho "1. COMPLETE VARIABLE AND FUNCTION DEFINITIONS" e cole-o no topo do arquivo main.js. Isso dá a você três variáveis que armazenam referências ao campo de texto "Inserir nome personalizado" (customName), o botão "Gerar história aleatória" (randomizar), E o elemento `<p>` na parte inferior do corpo HTML para onde a história será copiada (história), respectivamente. Além disso, você tem uma função chamada randomValueFromArray () que recebe um vetor e retorna um dos itens armazenados dentro do vetor aleatoriamente.
2. Agora, veja a segunda seção do arquivo de texto bruto - "2. RAW TEXT STRINGS". Ele contém strings de texto que atuarão como entrada em nosso programa. Gostaríamos que você armazenasse essas strings dentro de variáveis no main.js:
    1. Armazene a primeira, grande e longa linha de texto dentro de uma variável chamada storyText.
    2. Armazene o primeiro conjunto de três strings dentro de um vetor chamado insertX.
    3. Armazene o segundo conjunto de três strings dentro de um vetor chamado insertY.
    4. Armazene o terceiro conjunto de três strings dentro de um vetor chamado insertZ.

Colocando o manipulador de eventos e a função incompleta:

1. Agora volte ao arquivo de texto bruto.
2. Copie o código encontrado abaixo do cabeçalho "3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION" E cole ele na parte inferior do arquivo main.js. Isto:
    * Adicione um ouvinte de evento de clique à variável randomize para que, quando o botão que ele representa, for clicado, a função `result()` seja executada.
    * Adicione a função `result()` parcialmente concluída ao seu código. Para o restante da avaliação, você estará preenchendo linhas dentro desta função para completá-la e fazê-la funcionar corretamente.

Completando a função `result()`:

1. Crie uma nova variável chamada `newStory`, e defina seu valor como igual a `storyText`. Isso é necessário para que possamos criar uma nova história aleatória toda vez que o botão for pressionado e a função for executada. Se fizermos alterações diretamente no `storyText`, só poderemos gerar uma nova história uma vez.
2. Crie três novas variáveis chamadas `xItem`, `yItem`, e `zItem`, e torne-as iguais ao resultado da chamada da função `randomValueFromArray()` em seus três arrays (o resultado em cada caso será um item aleatório de cada array em que é chamado). Por exemplo, você pode chamar a função e fazer com que ela retorne uma string aleatória de `insertX` escrevendo `randomValueFromArray(insertX)`.
3. Em seguida, queremos substituir os três espaços reservados na variável `newStory` — `:insertx:`, `:inserty:`, e `:insertz:` — com strings armazenadas em `xItem`, `yItem`, e `zItem`. Existe um método de string específico que irá ajudá-lo aqui - em cada caso, faça a chamada para o método igual a `newStory`,então cada vez que é chamado, newStory é igual a si mesmo, mas com substituições feitas. Assim, cada vez que o botão é pressionado, esses espaços reservados são substituídos por uma string boba aleatória. Como uma dica adicional, o método em questão substitui apenas a primeira ocorrência da subseqüência de caracteres encontrada, portanto, talvez seja necessário fazer uma das chamadas duas vezes.
4. Dentro do primeiro bloco `if`, adicione outra chamada de método de substituição de string para substituir o nome 'Bob' encontrado na string `newStory` pela variável `name`. Neste bloco estamos dizendo "Se um valor foi inserido na entrada de texto `customName`, substitua Bob na história por esse nome personalizado ".
5. Dentro do segundo bloco `if`, estamos verificando se o botão de opção `uk` foi selecionado. Se assim for, converteremos os valores de peso e temperatura na história de libras e Fahrenheit em graus centígrados. O que você precisa fazer é o seguinte:
    1. Procure as fórmulas para converter libras em pedras e Fahrenheit em centígrados.
    2. Dentro da linha que define a variável `weight`, substitua 300 por um cálculo que converta 300 libras em pedras. Concatene `' stone'` no final do resultado da chamada geral `Math.round()`.
    3. Dentro da linha que define a variável `temperature`, substitua 94 por um cálculo que converta 94 graus Fahrenheit em graus centígrados. Concatene `' centigrade'` no resultado da chamada geral `Math.round()`.
    4. Apenas sob as duas definições de variáveis, adicione mais duas linhas de substituição de string que substituem '94 fahrenheit' pelo conteúdo da variável `temperature`, e '300 libras' com o conteúdo da variável `weight`.
6. Finalmente, na segunda e última linha da função, torne a propriedade`textContent` da variável `story` (que faz referência ao parágrafo) igual a `newStory`.
Dicas e sugestões
-----------------

* Você não precisa editar o HTML de nenhuma maneira, exceto para adicionar o JavaScript ao seu HTML.
* Se você não tiver certeza se o JavaScript é aplicado ao seu HTML corretamente, tente remover todo o restante do arquivo JavaScript temporariamente, adicionando um pouco de JavaScript que você sabe que criará um efeito óbvio, salvando e atualizando. Por exemplo, o seguinte transforma o plano de fundo do elemento `<html>` em vermelho - para que a janela inteira do navegador fique vermelha se o JavaScript for aplicado corretamente:

```js
document.querySelector("html").style.backgroundColor = "red";
```

* Math.round() é um método JavaScript integrado que simplesmente arredonda o resultado de um cálculo para o número inteiro mais próximo.
Avaliação
---------

Se você estiver seguindo esta avaliação como parte de um curso organizado, você está apto a entregar seu trabalho ao seu professor/mentor para avaliação. Se você é auto-didata, então você pode consultar o guia de marcação com bastante facilidade perguntando no tópico do Discurso da área de aprendizagem, ou no no canal #mdn IRC no IRC Mozilla. Tente realizar o exercício primeiro — não há nada a ganhar com a trapaça!

* Anterior
* Menu: First steps