From 68fc8e96a9629e73469ed457abd955e548ec670c Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 14:49:58 +0100 Subject: unslug pt-br: move --- .../pt-br/web/javascript/guide/closures/index.html | 336 ---------- .../cole\303\247\303\265es_chaveadas/index.html" | 149 ----- .../control_flow_and_error_handling/index.html | 429 +++++++++++++ .../guide/declara\303\247\303\265es/index.html" | 429 ------------- .../guide/details_of_the_object_model/index.html | 705 +++++++++++++++++++++ .../guide/detalhes_do_modelo_do_objeto/index.html | 705 --------------------- .../javascript/guide/formatando_texto/index.html | 250 -------- .../web/javascript/guide/functions/index.html | 640 +++++++++++++++++++ .../guide/fun\303\247\303\265es/index.html" | 640 ------------------- .../javascript/guide/grammar_and_types/index.html | 601 ++++++++++++++++++ .../web/javascript/guide/igualdade/index.html | 259 -------- .../inheritance_and_the_prototype_chain/index.html | 193 ------ .../guide/iteratores_e_geradores/index.html | 161 ----- .../guide/iterators_and_generators/index.html | 161 +++++ .../javascript/guide/lacos_e_iteracoes/index.html | 333 ---------- .../guide/loops_and_iteration/index.html | 333 ++++++++++ .../pt-br/web/javascript/guide/modules/index.html | 454 +++++++++++++ .../javascript/guide/m\303\263dulos/index.html" | 454 ------------- .../javascript/guide/numbers_and_dates/index.html | 374 +++++++++++ .../javascript/guide/numeros_e_datas/index.html | 374 ----------- .../javascript/guide/sintaxe_e_tipos/index.html | 583 ----------------- .../javascript/guide/text_formatting/index.html | 250 ++++++++ .../guide/trabalhando_com_objetos/index.html | 494 --------------- .../javascript/guide/usando_promises/index.html | 269 -------- .../web/javascript/guide/using_promises/index.html | 269 ++++++++ .../values,_variables,_and_literals/index.html | 601 ------------------ .../guide/working_with_objects/index.html | 494 +++++++++++++++ 27 files changed, 4710 insertions(+), 6230 deletions(-) delete mode 100644 files/pt-br/web/javascript/guide/closures/index.html delete mode 100644 "files/pt-br/web/javascript/guide/cole\303\247\303\265es_chaveadas/index.html" create mode 100644 files/pt-br/web/javascript/guide/control_flow_and_error_handling/index.html delete mode 100644 "files/pt-br/web/javascript/guide/declara\303\247\303\265es/index.html" create mode 100644 files/pt-br/web/javascript/guide/details_of_the_object_model/index.html delete mode 100644 files/pt-br/web/javascript/guide/detalhes_do_modelo_do_objeto/index.html delete mode 100644 files/pt-br/web/javascript/guide/formatando_texto/index.html create mode 100644 files/pt-br/web/javascript/guide/functions/index.html delete mode 100644 "files/pt-br/web/javascript/guide/fun\303\247\303\265es/index.html" create mode 100644 files/pt-br/web/javascript/guide/grammar_and_types/index.html delete mode 100644 files/pt-br/web/javascript/guide/igualdade/index.html delete mode 100644 files/pt-br/web/javascript/guide/inheritance_and_the_prototype_chain/index.html delete mode 100644 files/pt-br/web/javascript/guide/iteratores_e_geradores/index.html create mode 100644 files/pt-br/web/javascript/guide/iterators_and_generators/index.html delete mode 100644 files/pt-br/web/javascript/guide/lacos_e_iteracoes/index.html create mode 100644 files/pt-br/web/javascript/guide/loops_and_iteration/index.html create mode 100644 files/pt-br/web/javascript/guide/modules/index.html delete mode 100644 "files/pt-br/web/javascript/guide/m\303\263dulos/index.html" create mode 100644 files/pt-br/web/javascript/guide/numbers_and_dates/index.html delete mode 100644 files/pt-br/web/javascript/guide/numeros_e_datas/index.html delete mode 100644 files/pt-br/web/javascript/guide/sintaxe_e_tipos/index.html create mode 100644 files/pt-br/web/javascript/guide/text_formatting/index.html delete mode 100644 files/pt-br/web/javascript/guide/trabalhando_com_objetos/index.html delete mode 100644 files/pt-br/web/javascript/guide/usando_promises/index.html create mode 100644 files/pt-br/web/javascript/guide/using_promises/index.html delete mode 100644 files/pt-br/web/javascript/guide/values,_variables,_and_literals/index.html create mode 100644 files/pt-br/web/javascript/guide/working_with_objects/index.html (limited to 'files/pt-br/web/javascript/guide') diff --git a/files/pt-br/web/javascript/guide/closures/index.html b/files/pt-br/web/javascript/guide/closures/index.html deleted file mode 100644 index efc7578d7d..0000000000 --- a/files/pt-br/web/javascript/guide/closures/index.html +++ /dev/null @@ -1,336 +0,0 @@ ---- -title: Closures -slug: Web/JavaScript/Guide/Closures -tags: - - Closure - - ES5 - - Intermediário - - JavaScript - - Referencia -translation_of: Web/JavaScript/Closures ---- -
{{jsSidebar("Intermediate")}}
- -

Um closure (fechamento) é uma função que se "lembra" do ambiente — ou escopo léxico — em que ela foi criada.

- -

Escopo léxico

- -

Considere a função abaixo:

- -
-
function init() {
-  var name = "Mozilla";
-  function displayName() {
-    alert(name);
-  }
-  displayName();
-}
-init();
-
-
- -

A função init() cria uma variável local chamada name, e depois define uma função chamada displayName(). displayName() é uma função aninhada (um closure) — ela é definida dentro da função init(), e está disponivel apenas dentro do corpo daquela função. Diferente de init(), displayName() não tem variáveis locais próprias, e ao invés disso reusa a variável name declarada na função pai.

- -

Rode o código e veja que isso funciona. Este é um exemplo de escopo léxico: em JavaScript, o escopo de uma variável é definido por sua localização dentro do código fonte (isto é aparentemente léxico) e funções aninhadas têm acesso às variáveis declaradas em seu escopo externo.

- -

Closure

- -

Agora considere o seguinte exemplo:

- -
function makeFunc() {
-  var name = "Mozilla";
-  function displayName() {
-    alert(name);
-  }
-  return displayName;
-}
-
-var myFunc = makeFunc();
-myFunc();
-
- -

Se você rodar este código o mesmo terá exatamente o mesmo efeito que o init() do exemplo anterior: a palavra "Mozilla" será mostrada na caixa de alerta. O que é diferente - e interessante - é o fato de que a função interna do displayName() foi retornada da função externa antes de ser executada.

- -

Pode parecer não muito intuitivo de que o código de fato funciona. Normalmente variáveis locais a uma função apenas existem pela duração da execução da mesma. Uma vez que makeFunc() terminou de executar, é razoável esperar que a variável name não será mais necessária. Dado que o código ainda funciona como o esperado, este não é o caso.

- -

A solução para tal problema é que a função myFunc tornou-se uma closure. Uma closure (fechamento) trata-se de um tipo especial de objeto que combina duas coisas: a função e o ambiente onde a função foi criada. Este ambiente consiste de quaisquer variáveis que estavam no escopo naquele momento em que a função foi criada. Neste caso, myFunc é a closure que incorpora tanto a função displayName quanto a palavra Mozilla que existia quando a closure foi criada.

- -

Aqui temos um exemplo um pouco mais interessante, a função makeAdder:

- -
function makeAdder(x) {
-  return function(y) {
-    return x + y;
-  };
-}
-
-var add5 = makeAdder(5);
-var add10 = makeAdder(10);
-
-print(add5(2));  // 7
-print(add10(2)); // 12
-
- -

Neste exemplo definimos a função makeAdder(x) que toma um único argumento x e retorna uma nova função. A função retornada toma então um único argumento, y, e retorna então a soma de x e de y.

- -

Na essência o makeAdder trata-se de uma função fábrica - irá construir outras funções que podem adicionar um determinado valor específico a seu argumento. No exemplo acima usamos a fábrica de funções para criar duas novas funções - uma que adiciona 5 ao argumento, e outra que adiciona 10.

- -

Ambas as funções add5 e add10 são closures. Compartilham o mesmo corpo de definição de função mas armazenam diferentes ambientes. No ambiente da add5, por exemplo, x equivale a 5, enquanto na add10 o valor de x é 10.

- -

Closures na prática

- -

Esta é a teoria — mas closures são realmente úteis? Vamos considerar suas aplicações práticas. Uma closure deixa você associar dados (do ambiente) com uma função que trabalha estes dados. Isto está diretamente ligado com programação orientada a objetos, onde objetos nos permitem associar dados (as propriedades do objeto) utilizando um ou mais métodos.

- -

Consequentemente, você pode utilizar uma closure em qualquer lugar onde você normalmente utilizaria um objeto de único método.

- -

Situações onde você poderia utilizar isto são comuns em ambientes web. Muitos códigos escritos em JavaScript para web são baseados em eventos - nós definimos algum comportamento e então, o atribuimos a um evento que será disparado pelo usuário (quando uma tecla for pressionada, por exemplo). Nosso código normalmente é utilizado como callback: uma função que será executada como resposta ao evento.

- -

Aqui temos um exemplo prático: suponha que queremos adicionar alguns botões para ajustar o tamanho do texto de uma página. Um jeito de fazer seria especificar o tamanho da fonte no elemento body e então definir o tamanho dos outros elementos da página (os cabeçalhos, por exemplo) utilizando a unidade relativa em:

- -
body {
-  font-family: Helvetica, Arial, sans-serif;
-  font-size: 12px;
-}
-
-h1 {
-  font-size: 1.5em;
-}
-h2 {
-  font-size: 1.2em;
-}
-
- -

Nossos botões interativos de tamanho de texto podem alterar a propriedade font-size do elemento body, e os ajustes serão refletidos em outros elementos graças à unidade relativa.

- -

O código JavaScript:

- -
function makeSizer(size) {
-  return function() {
-    document.body.style.fontSize = size + 'px';
-  };
-}
-
-var size12 = makeSizer(12);
-var size14 = makeSizer(14);
-var size16 = makeSizer(16);
-
- -

size12, size14 e size16 agora são funções que devem redimensionar o texto do elemento body para 12, 14 e 16 pixels respectivamente. Nós podemos designá-las a botões (neste caso, links) como feito a seguir:

- -
document.getElementById('size-12').onclick = size12;
-document.getElementById('size-14').onclick = size14;
-document.getElementById('size-16').onclick = size16;
-
- -
<a href="#" id="size-12">12</a>
-<a href="#" id="size-14">14</a>
-<a href="#" id="size-16">16</a>
-
- -

View on JSFiddle

- -

Emulando métodos privados com closures

- -

Linguagens como Java oferecem a habilidade de declarar métodos privados, o que significa que eles só poderão ser chamados por outros métodos na mesma classe.

- -

O JavaScript não oferece uma maneira nativa de fazer isso, mas é possível emular métodos privados usando closures. Métodos privados não são somente úteis para restringir acesso ao código: eles também oferecem uma maneira eficaz de gerenciar seu namespace global, evitando que métodos não essenciais baguncem a interface pública do seu código.

- -

Veja como definir algumas funções públicas que acessam funções e variáveis privadas, usando closures que também é conhecido como module pattern:

- -
var Counter = (function() {
-  var privateCounter = 0;
-  function changeBy(val) {
-    privateCounter += val;
-  }
-  return {
-    increment: function() {
-      changeBy(1);
-    },
-    decrement: function() {
-      changeBy(-1);
-    },
-    value: function() {
-      return privateCounter;
-    }
-  }
-})();
-
-alert(Counter.value()); /* Alerts 0 */
-Counter.increment();
-Counter.increment();
-alert(Counter.value()); /* Alerts 2 */
-Counter.decrement();
-alert(Counter.value()); /* Alerts 1 */
-
- -

Tem muita coisa acontecendo aqui. Nos exemplos anteriores cada closure teve o seu próprio ambiente; aqui nós criamos um ambiente único que é compartilhado por três funções: Counter.increment, Counter.decrement e Counter.value.

- -

O ambiente compartilhado é criado no corpo de uma função anônima, da qual é executada assim que é definida. O ambiente contém dois itens privados: uma variável chamada privateCounter e uma função chamada changeBy. Nenhum desses itens privados podem ser acessados diretamente de fora da função anônima. Ao invés disso, eles devem ser acessados pelas três funções públicas que são retornadas.

- -

Aquelas três funções públicas são closures que compartilham o mesmo ambiente. Graças ao escopo léxico do JavaScript, cada uma delas tem acesso a variável privateCounter e à função changeBy.

- -
-

Você perceberá que estamos definindo uma função anônima que cria um contador , e então o executamos imediatamente e atribuímos o resultado à variável Counter. Poderíamos armazenar essa função em uma variável separada e usá-la para criar diversos contadores.

-
- -
var makeCounter = function() {
-  var privateCounter = 0;
-  function changeBy(val) {
-    privateCounter += val;
-  }
-  return {
-    increment: function() {
-      changeBy(1);
-    },
-    decrement: function() {
-      changeBy(-1);
-    },
-    value: function() {
-      return privateCounter;
-    }
-  }
-};
-
-var Counter1 = makeCounter();
-var Counter2 = makeCounter();
-alert(Counter1.value()); /* Alerts 0 */
-Counter1.increment();
-Counter1.increment();
-alert(Counter1.value()); /* Alerts 2 */
-Counter1.decrement();
-alert(Counter1.value()); /* Alerts 1 */
-alert(Counter2.value()); /* Alerts 0 */
-
- -

Observe como cada um dos contadores mantém a sua independência em relação ao outro. Seu ambiente durante a execução da função makeCounter() é diferente a cada vez que ocorre. A variável privateCounter contém uma instância diferente a cada vez.

- -
-

Usar closures desta maneira oferece uma série de benefícios que estão normalmente associados a programação orientada a objetos, em particular encapsulamento e ocultação de dados.

-
- -
-
- -

Criando closures dentro de loops: Um erro comum

- -

Antes da introdução da palavra chave let no JavaScript 1.7, um problema comum ocorria com closures quando eram criadas dentro de um loop. Considere o exemplo:

- -
<p id="help">Helpful notes will appear here</p>
-<p>E-mail: <input type="text" id="email" name="email"></p>
-<p>Name: <input type="text" id="name" name="name"></p>
-<p>Age: <input type="text" id="age" name="age"></p>
-
- -
function showHelp(help) {
-  document.getElementById('help').innerHTML = help;
-}
-
-function setupHelp() {
-  var helpText = [
-      {'id': 'email', 'help': 'Your e-mail address'},
-      {'id': 'name', 'help': 'Your full name'},
-      {'id': 'age', 'help': 'Your age (you must be over 16)'}
-    ];
-
-  for (var i = 0; i < helpText.length; i++) {
-    var item = helpText[i];
-    document.getElementById(item.id).onfocus = function() {
-      showHelp(item.help);
-    }
-  }
-}
-
-setupHelp();
-
- -

View on JSFiddle

- -

O array helpText define três dicas úteis, cada uma associada ao ID de um input no documento. O loop percorre essas definições, atrelando um evento onfocus para cada um que mostra o método de ajuda associado.

- -

Se você tentar executar esse código, Você verá que não vai funcionar como esperado. Não importa em qual campo ocorre o focus, a mensagem sobre a sua idade será mostrada.

- -

O motivo disto é que as funções atreladas ao onfocus são closures; elas consistem na definição da função e do ambiente capturado do escopo da função setupHelp. Três closures foram criados, mas todos eles compartilham o mesmo ambiente. No momento em que os callbacks do onfocus são executados, o loop segue seu curso e então a variável item (compartilhada por todos os três closures) fica apontando para a última entrada na lista helpText.

- -

Uma solução seria neste caso usar mais closures: em particular, usar uma fábrica de funções como descrito anteriormente:

- -
function showHelp(help) {
-  document.getElementById('help').innerHTML = help;
-}
-
-function makeHelpCallback(help) {
-  return function() {
-    showHelp(help);
-  };
-}
-
-function setupHelp() {
-  var helpText = [
-      {'id': 'email', 'help': 'Your e-mail address'},
-      {'id': 'name', 'help': 'Your full name'},
-      {'id': 'age', 'help': 'Your age (you must be over 16)'}
-    ];
-
-  for (var i = 0; i < helpText.length; i++) {
-    var item = helpText[i];
-    document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
-  }
-}
-
-setupHelp();
-
- -

View on JSFiddle

- -

Isto funciona conforme o esperado. Ao invés dos callbacks compartilharem o mesmo ambiente, a função makeHelpCallback cria um novo ambiente para cada um no qual help se refere à string correspondente do array helpText.

- -

Considerações de performance

- -

Não é sábio criar funções dentro de outras funções se o closure não for necessário para uma tarefa em particular, pois ele afetará a performance do script de forma bem negativa tanto em velocidade de processamento quanto em consumo de memória.

- -

Por exemplo, ao criar uma nova classe/objeto, os métodos devem normalmente estar associados ao protótipo do objeto do que definido no construtor. O motivo disso é que sempre que o construtor for chamado os métodos serão reatribuídos (isto é, para cada criação de objeto).

- -

Considere o seguinte exemplo pouco prático porém demonstrativo:

- -
function MyObject(name, message) {
-  this.name = name.toString();
-  this.message = message.toString();
-  this.getName = function() {
-    return this.name;
-  };
-
-  this.getMessage = function() {
-    return this.message;
-  };
-}
-
- -

O código anterior não aproveita os benefícios dos closures e portanto poderia ser reformulado assim:

- -
function MyObject(name, message) {
-  this.name = name.toString();
-  this.message = message.toString();
-}
-MyObject.prototype = {
-  getName: function() {
-    return this.name;
-  },
-  getMessage: function() {
-    return this.message;
-  }
-};
-
- -

Ou assim:

- -
function MyObject(name, message) {
-  this.name = name.toString();
-  this.message = message.toString();
-}
-MyObject.prototype.getName = function() {
-  return this.name;
-};
-MyObject.prototype.getMessage = function() {
-  return this.message;
-};
-
- -

Nos dois exemplos anteriores, o protótipo herdado pode ser compartilhado por todos os objetos, e as definições de métodos não precisam ocorrer sempre que o objeto for criado. Veja Detalhes do modelo de objeto para mais detalhes.

diff --git "a/files/pt-br/web/javascript/guide/cole\303\247\303\265es_chaveadas/index.html" "b/files/pt-br/web/javascript/guide/cole\303\247\303\265es_chaveadas/index.html" deleted file mode 100644 index cb626865f8..0000000000 --- "a/files/pt-br/web/javascript/guide/cole\303\247\303\265es_chaveadas/index.html" +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Coleções chaveadas -slug: Web/JavaScript/Guide/Coleções_chaveadas -tags: - - Coleções - - Guía - - JavaScript - - Mapas ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}
- -

This chapter introduces collections of data which are ordered by a key; Map and Set objects contain elements which are iterable in the order of insertion.

- -

Maps

- -

Map object

- -

ECMAScript 6 introduces a new data structure to map values to values. A {{jsxref("Map")}} object is a simple key/value map and can iterate its elements in insertion order

- -

The following code shows some basic operations with a Map. See also the {{jsxref("Map")}} reference page for more examples and the complete API. You can use a {{jsxref("Statements/for...of","for...of")}} loop to return an array of [key, value] for each iteration.

- -
var sayings = new Map();
-sayings.set("dog", "woof");
-sayings.set("cat", "meow");
-sayings.set("elephant", "toot");
-sayings.size; // 3
-sayings.get("fox"); // undefined
-sayings.has("bird"); // false
-sayings.delete("dog");
-
-for (var [key, value] of sayings) {
-  console.log(key + " goes " + value);
-}
-// "cat goes meow"
-// "elephant goes toot"
-
- -

Object and Map compared

- -

Traditionally, {{jsxref("Object", "objects", "", 1)}} have been used to map strings to values. Objects allow you to set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. Map objects, however, have a few more advantages that make them better maps.

- - - -

These two tips can help you to decide whether to use a Map or an Object:

- - - -

WeakMap object

- -

The {{jsxref("WeakMap")}} object is a collection of key/value pairs in which the keys are objects only and the values can be arbitrary values. The object references in the keys are held weakly meaning that they are target of garbage collection (GC) if there is no other reference to the object anymore. The WeakMap API is the same as the Map API.

- -

One difference to Map objects is that WeakMap keys are not enumerable (i.e. there is no method giving you a list of the keys). If they were, the list would depend on the state of garbage collection, introducing non-determinism.

- -

For more information and example code, see also "Why WeakMap?" on the {{jsxref("WeakMap")}} reference page.

- -

One use case of WeakMap objects is to store private data for an object or to hide implementation details. The following example is from Nick Fitzgerald blog post "Hiding Implementation Details with ECMAScript 6 WeakMaps". The private data and methods belong inside the object and are stored in the privates WeakMap object. Everything exposed on the instance and prototype is public; everything else is inaccessible from the outside world because privates is not exported from the module

- -
const privates = new WeakMap();
-
-function Public() {
-  const me = {
-    // Private data goes here
-  };
-  privates.set(this, me);
-}
-
-Public.prototype.method = function () {
-  const me = privates.get(this);
-  // Do stuff with private data in `me`...
-};
-
-module.exports = Public;
-
- -

Sets

- -

Set object

- -

{{jsxref("Set")}} objects are collections of values. You can iterate its elements in insertion order. A value in a Set may only occur once; it is unique in the Set's collection.

- -

The following code shows some basic operations with a Set. See also the {{jsxref("Set")}} reference page for more examples and the complete API.

- -
var mySet = new Set();
-mySet.add(1);
-mySet.add("some text");
-mySet.add("foo");
-
-mySet.has(1); // true
-mySet.delete("foo");
-mySet.size; // 2
-
-for (let item of mySet) console.log(item);
-// 1
-// "some text"
-
- -

Converting between Array and Set

- -

You can create an {{jsxref("Array")}} from a Set using {{jsxref("Array.from")}} or the spread operator. Also, the Set constructor accepts an Array to convert in the other direction. Note again that Set objects store unique values, so any duplicate elements from an Array are deleted when converting.

- -
Array.from(mySet);
-[...mySet2];
-
-mySet2 = new Set([1,2,3,4]);
-
- -

Array and Set compared

- -

Traditionally, a set of elements has been stored in arrays in JavaScript in a lot of situations. The new Set object, however, has some advantages:

- - - -

WeakSet object

- -

{{jsxref("WeakSet")}} objects are collections of objects. An object in the WeakSet may only occur once; it is unique in the WeakSet's collection and objects are not enumerable.

- -

The main differences to the {{jsxref("Set")}} object are:

- - - -

The use cases of WeakSet objects are limited. They will not leak memory so it can be safe to use DOM elements as a key and mark them for tracking purposes, for example.

- -

Key and value equality of Map and Set

- -

Both, the key equality of Map objects and the value equality of Set objects, are based on the "same-value-zero algorithm":

- - - -

{{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}

diff --git a/files/pt-br/web/javascript/guide/control_flow_and_error_handling/index.html b/files/pt-br/web/javascript/guide/control_flow_and_error_handling/index.html new file mode 100644 index 0000000000..e352b58f6d --- /dev/null +++ b/files/pt-br/web/javascript/guide/control_flow_and_error_handling/index.html @@ -0,0 +1,429 @@ +--- +title: Controle de Fluxo e Manipulação de Erro +slug: Web/JavaScript/Guide/Declarações +tags: + - Guia(2) + - Iniciante + - JavaScript + - declarações + - declarações de controle +translation_of: Web/JavaScript/Guide/Control_flow_and_error_handling +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}
+ +

O JavaScript suporta um conjunto compacto de declarações, especificamente de fluxo de controle, que você pode utilizar para atribuir uma grande interatividade a páginas web. Este capítulo fornece uma visão geral destas declarações.

+ +

Veja a Referência do JavaScript para detalhes sobre as declarações mostradas neste capítulo. No código em JavaScript, o caractere ponto e vírgula (;) é utilizado para separar declarações.

+ +

Toda expressão também é uma declaração. Veja Expressões e Operadores para informações completas sobre expressões.

+ +

Declaração em bloco

+ +

Uma declaração em bloco é utilizada para agrupar declarações. O bloco é delimitado por um par de chaves:

+ +
{
+   declaracao_1;
+   declaracao_2;
+   .
+   .
+   .
+   declaracao_n;
+}
+
+ +

Exemplo

+ +

Declarações em bloco são utilizadas geralmente com declarações de fluxo de controle (ex. if, for, while).

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

Aqui, { x++; } é a declaração de bloco.

+ +

ImportanteAntes de ECMAScript 6 o JavaScript não possuía escopo de bloco. Variáveis introduzidas dentro de um bloco possuem como escopo a função ou o script em que o bloco está contido, e, definir tais variáveis tem efeito muito além do bloco em si. Em outras palavras, declarações de bloco não introduzem um escopo. Embora blocos "padrão" sejam uma sintaxe válida não utilize-os, em JavaScript, pensando que funcionam como em C ou Java porque eles não funcionam da maneira que você acredita. Por exemplo:

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

Este código exibe 2 porque a declaração var x dentro do bloco possui o mesmo escopo que a declaração var x antes do bloco. Em C ou Java, o código equivalente exibiria 1.

+ +

Declarações condicionais

+ +

Uma declaração condicional é um conjunto de comandos que são executados caso uma condição especificada seja verdadeira. O JavaScript suporta duas declarações condicionais: if...else e switch.

+ +

Declaração if...else

+ +

Use a declaração if para executar alguma declaração caso a condição lógica for verdadeira. Use a cláusula opcional else para executar alguma declaração caso a condição lógica for falsa. Uma declaração if é declarada da seguinte maneira:

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

onde condicao pode ser qualquer expressão que seja avaliada como verdadeira ou falsa. Veja Boolean para uma explicação sobre o que é avaliado como true e falseSe condicao for avaliada como verdadeira, declaracao_1 é executada; caso contrário, declaracao_2 é executada. declaracao_1 e declaracao_2 podem ser qualquer declaração, incluindo declarações if aninhadas.

+ +

Você pode também combinar declarações utilizando else if para obter várias condições testadas em sequência, como o seguinte:

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

Para executar várias declarações, agrupe-as em uma declaração em bloco ({ ... }). Em geral, é uma boa prática sempre utilizar declarações em bloco, especialmente ao aninhar declarações if:

+ +
if (condicao) {
+    declaracao_1_executada_se_condicao_for_verdadeira;
+    declaracao_2_executada_se_condicao_for_verdadeira;
+} else {
+    declaracao_3_executada_se_condicao_for_falsa;
+    declaracao_4_executada_se_condicao_for_falsa;
+}
+
+ +
Recomenda-se não utilizar atribuições simples em uma expressão condicional porque o símbolo de atribuição poderia ser confundido com o de igualdade ao dar uma olhada no código. Por exemplo, não utilize o seguinte código:
+ +
if (x = y) {
+  /* faça a coisa certa */
+}
+
+ +

Caso tenha que utilizar uma atribuição em uma expressão condicional, uma prática comum é colocar parênteses adicionais em volta da atribuição. Por exemplo:

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

Valores avaliados como falsos

+ +

Os seguintes valores são avaliados como falsos:

+ + + +

Todos os outros valores, incluindo todos os objetos, são avaliados como verdadeiros quando passados para uma declaração condicional.

+ +

Não confunda os valores booleanos primitivos true e false com os valores de true e false do objeto Boolean. Por exemplo:

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

 

+ +

Exemplo

+ +

No exemplo a seguir, a função verifiqueDados retorna verdadeiro se o número de caracteres em um objeto Text for três; caso contrário, exibe um alerta e retorna falso.

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

Declaração switch

+ +

Uma declaração switch permite que um programa avalie uma expressão e tente associar o valor da expressão ao rótulo de um case. Se uma correspondência é encontrada, o programa executa a declaração associada. Uma declaração switch se parece com o seguinte:

+ +
switch (expressao) {
+   case rotulo_1:
+      declaracoes_1
+      [break;]
+   case rotulo_2:
+      declaracoes_2
+      [break;]
+   ...
+   default:
+      declaracoes_padrao
+      [break;]
+}
+
+ +

O programa primeiramente procura por uma cláusula case com um rótulo que corresponda ao valor da expressão e então transfere o controle para aquela cláusula, executando as declaracoes associadas. Se nenhum rótulo correspondente é encontrado, o programa procura pela cláusula opcional default e, se encontrada, transfere o controle àquela cláusula, executando as declarações associadas. Se nenhuma cláusula default é encontrada, o programa continua a execução a partir da declaracao seguinte ao switch. Por convenção, a cláusula default é a última, mas não é necessário que seja assim.

+ +

A instrução break associada a cada cláusula case, garante que o programa sairá do switch assim que a declaração correspondente for executada e que continuará a execução a partir da declaração seguinte ao switch. Se a declaração break for omitida, o programa continua a execução a partir da próxima declaração dentro do switch.

+ +

Exemplo

+ +

No exemplo a seguir, se tipofruta for avaliada como "Banana", o programa faz a correspondência do valor com case "Banana" e executa a declaração associada. Quando o break é encontrado, o programa termina o switch e executa a declaração seguinte ao condicional. Se o break fosse omitido, a declaração de case "Cereja" também seria executada.

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

Declarações de Manipulação de Error

+ +

Você pode chamar uma exceção usando a declaração throw e manipulá-la usando a declaração try...catch.

+ + + +

Tipos de exceções

+ +

Praticamente pode-se utilizar throw em qualquer objeto de JavaScript. Todavia, nem todos os objetos ativados por throw são igualmente criados. Embora seja bastante comum tratar números ou strings como erros usando throw, é frequentemente mais eficiente usar alguns tipos de exceções especificamente criadas para esses propósitos:

+ + + +

Declaração throw

+ +

Use a declaração throw para lançar uma exceção. Quando você lança uma exceção, você especifica a expressão contendo o valor a ser lançado:

+ +
throw expressão;
+
+ +

Você pode lançar qualquer expressão, não apenas expressões de um tipo específico. O código a seguir lança várias exceções de diferentes tipos:

+ +
throw "Error2";   // tipo string
+throw 42;         // tipo numérico
+throw true;       // tipo booleano
+throw {toString: function() { return "Eu sou um objeto!"; } };
+
+ +
Nota:  Você pode especificar um objeto quando você lança uma exceção. Você pode então, referenciar as propriedades de um objeto no bloco catch.  O exemplo a seguir cria um objeto myUserException do tipo userException e o usa em uma declaração throw.
+ +
// Cria um objeto do tipo UserException
+function UserException(mensagem) {
+  this.mensagem = mensagem;
+  this.nome = "UserException";
+}
+
+// Realiza a conversão da exceção para uma string adequada quando usada como uma string.
+// (ex. pelo console de erro)
+UserException.prototype.toString = function() {
+  return this.name + ': "' + this.message + '"';
+}
+
+// Cria uma instância de um tipo de objeto e lança ela
+throw new UserException("Valor muito alto");
+ +

Declaração try...catch

+ +

A declaração try...catch coloca um bloco de declarações em try, e especifica uma ou mais respostas para uma exceção lançada. Se uma exceção é lançada, a declaração try...catch pegá-a.

+ +

A declaração try...catch é composta por um bloco try, que contém uma ou mais declarações, e zero ou mais blocos catch, contendo declarações que especificam o que fazer se uma exceção é lançada no bloco try. Ou seja, você deseja que o bloco try  tenha sucesso, e se ele não tiver êxito, você quer o controle passado para o bloco catch. Se qualquer declaração do bloco try (ou em uma função chamada dentro do bloco try) lança uma exceção, o controle é imediatamente mudado para o bloco catch. Se nenhuma exceção é lançada no bloco try, o bloco catch é ignorado. O bloco finally executa após os blocos try e catch executarem, mas antes das declarações seguinte ao bloco try...catch.

+ +

O exemplo a seguir usa a declaração try...catch. O exemplo chama uma função que recupera o nome de um mês no array com base no valor passado para a função. Se o valor não corresponde ao número de um mês (1-12), uma exceção é lançada com o valor "InvalidMonthNo" e as declarações no bloco catch define a váriavel monthName para unknown.

+ +
function getMonthName(mo) {
+  mo = mo - 1; // Ajusta o número do mês para o índice do array (1 = Jan, 12 = Dec)
+  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul",
+                "Aug","Sep","Oct","Nov","Dec"];
+  if (months[mo]) {
+    return months[mo];
+  } else {
+    throw "InvalidMonthNo"; //lança uma palavra-chave aqui usada.
+  }
+}
+
+try { // statements to try
+  monthName = getMonthName(myMonth); // função poderia lançar uma exceção
+}
+catch (e) {
+  monthName = "unknown";
+  logMyErrors(e); // passa a exceção para o manipulador de erro -> sua função local.
+}
+
+ +

O bloco catch

+ +

Você pode usar um bloco catch para lidar com todas as exceções que podem ser geradas no bloco try.

+ +
catch (catchID) {
+  declaracoes
+}
+
+ +

O bloco catch específica um identificador (catchID na sintaxe anterior), que contém o valor especificado pela declaração throw; você pode usar esse identificador para obter informações sobre a exceção que foi lançada. JavaScript cria este identificador quando o bloco catch é inserido; o identificador dura enquanto o bloco catch está em execução, depois que termina a execução do bloco catch, o identificador não estará mais disponível.

+ +

Por exemplo, o seguinte código lança uma exceção. Quando a exceção ocorre, o controle é transferido para o bloco catch.

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

O bloco finally

+ +

O bloco finally contém instruções para executar após os blocos try e catch, mas antes das declarações seguinte a declaração try...catch. O bloco finally é executado com ou sem o lançamento de uma exceção. Se uma exceção é lançada, a declaração no bloco finally executa, mesmo que nenhum bloco catch processe a exceção.

+ +

Você pode usar bloco finally para deixar a falha de seu script agradável quando uma exceção ocorre; por exemplo, você pode precisar liberar um recurso que seu script tem amarrado. O exemplo a seguir abre um arquivo e então executa instruções que usam o arquivo (JavaScript do lado do servidor permite que você acesse arquivos). Se um exceção é lançada enquanto o arquivo é aberto, o bloco finally fecha o arquivo antes do script falhar.

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

Se o bloco finally retornar um valor, este valor se torna o valor de toda a entrada try-catch-finally, independente de quaisquer declarações de retorno nos blocos try e catch:

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

Substituições de valores de retorno pelo bloco finally também se aplica a exceções lançadas ou re-lançadas dentro do bloco catch:

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

Aninhando declarações try...catch

+ +

Você pode aninhar uma ou mais declarações try...catch. Se uma declaração try...catch interior não tem um bloco catch, o delimitador do bloco try...catch da declaração catch é verificado por uma correspondência.

+ +

Utilizando objetos de erro

+ +

Dependendo do tipo de erro, você pode ser capaz de usar as propriedade 'name' e 'message' para pegar uma mensagem mais refinada. A propriedade 'name' fornece a classe geral de erro (ex., 'DOMException' ou 'Error'), enquanto 'message' geralmente oferece uma mensagem mais sucinta do que se poderia obter através da conversão do objeto de erro para uma string.

+ +

Se você está lançando suas próprias exceções, a fim de tirar proveito dessas propriedades (como o seu bloco catch não discrimina entre suas próprias exceções e as exceções próprias da linguagem), você pode usar o construtor Error. Por exemplo:

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

Promises

+ +

Começando com ECMAScript 6, JavaScript ganha suporte para objetos {{jsxref("Promise")}} que lhe permite controlar o fluxo de operações diferídas e assíncronas.

+ +

Uma Promise assume um destes estados:

+ + + +

+ +

Carregando uma imagem com XHR

+ +

Um exemplo simples usando Promise e XMLHttpRequest para carregar uma imagem disponível no repositório MDN GitHub promise-test. Você também pode vê-lo executando. Cada etapa está comentada o que lhe permite seguir de perto a arquitetura Promise e arquitetura XHR. Aqui está a versão não comentada, mostrando o fluxo Promise para que você possa ter uma ideia:

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

Para uma informação mais detalhada, consulte a página de referência {{jsxref("Promise")}}.

+ +
{{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}
diff --git "a/files/pt-br/web/javascript/guide/declara\303\247\303\265es/index.html" "b/files/pt-br/web/javascript/guide/declara\303\247\303\265es/index.html" deleted file mode 100644 index e352b58f6d..0000000000 --- "a/files/pt-br/web/javascript/guide/declara\303\247\303\265es/index.html" +++ /dev/null @@ -1,429 +0,0 @@ ---- -title: Controle de Fluxo e Manipulação de Erro -slug: Web/JavaScript/Guide/Declarações -tags: - - Guia(2) - - Iniciante - - JavaScript - - declarações - - declarações de controle -translation_of: Web/JavaScript/Guide/Control_flow_and_error_handling ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}
- -

O JavaScript suporta um conjunto compacto de declarações, especificamente de fluxo de controle, que você pode utilizar para atribuir uma grande interatividade a páginas web. Este capítulo fornece uma visão geral destas declarações.

- -

Veja a Referência do JavaScript para detalhes sobre as declarações mostradas neste capítulo. No código em JavaScript, o caractere ponto e vírgula (;) é utilizado para separar declarações.

- -

Toda expressão também é uma declaração. Veja Expressões e Operadores para informações completas sobre expressões.

- -

Declaração em bloco

- -

Uma declaração em bloco é utilizada para agrupar declarações. O bloco é delimitado por um par de chaves:

- -
{
-   declaracao_1;
-   declaracao_2;
-   .
-   .
-   .
-   declaracao_n;
-}
-
- -

Exemplo

- -

Declarações em bloco são utilizadas geralmente com declarações de fluxo de controle (ex. if, for, while).

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

Aqui, { x++; } é a declaração de bloco.

- -

ImportanteAntes de ECMAScript 6 o JavaScript não possuía escopo de bloco. Variáveis introduzidas dentro de um bloco possuem como escopo a função ou o script em que o bloco está contido, e, definir tais variáveis tem efeito muito além do bloco em si. Em outras palavras, declarações de bloco não introduzem um escopo. Embora blocos "padrão" sejam uma sintaxe válida não utilize-os, em JavaScript, pensando que funcionam como em C ou Java porque eles não funcionam da maneira que você acredita. Por exemplo:

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

Este código exibe 2 porque a declaração var x dentro do bloco possui o mesmo escopo que a declaração var x antes do bloco. Em C ou Java, o código equivalente exibiria 1.

- -

Declarações condicionais

- -

Uma declaração condicional é um conjunto de comandos que são executados caso uma condição especificada seja verdadeira. O JavaScript suporta duas declarações condicionais: if...else e switch.

- -

Declaração if...else

- -

Use a declaração if para executar alguma declaração caso a condição lógica for verdadeira. Use a cláusula opcional else para executar alguma declaração caso a condição lógica for falsa. Uma declaração if é declarada da seguinte maneira:

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

onde condicao pode ser qualquer expressão que seja avaliada como verdadeira ou falsa. Veja Boolean para uma explicação sobre o que é avaliado como true e falseSe condicao for avaliada como verdadeira, declaracao_1 é executada; caso contrário, declaracao_2 é executada. declaracao_1 e declaracao_2 podem ser qualquer declaração, incluindo declarações if aninhadas.

- -

Você pode também combinar declarações utilizando else if para obter várias condições testadas em sequência, como o seguinte:

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

Para executar várias declarações, agrupe-as em uma declaração em bloco ({ ... }). Em geral, é uma boa prática sempre utilizar declarações em bloco, especialmente ao aninhar declarações if:

- -
if (condicao) {
-    declaracao_1_executada_se_condicao_for_verdadeira;
-    declaracao_2_executada_se_condicao_for_verdadeira;
-} else {
-    declaracao_3_executada_se_condicao_for_falsa;
-    declaracao_4_executada_se_condicao_for_falsa;
-}
-
- -
Recomenda-se não utilizar atribuições simples em uma expressão condicional porque o símbolo de atribuição poderia ser confundido com o de igualdade ao dar uma olhada no código. Por exemplo, não utilize o seguinte código:
- -
if (x = y) {
-  /* faça a coisa certa */
-}
-
- -

Caso tenha que utilizar uma atribuição em uma expressão condicional, uma prática comum é colocar parênteses adicionais em volta da atribuição. Por exemplo:

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

Valores avaliados como falsos

- -

Os seguintes valores são avaliados como falsos:

- - - -

Todos os outros valores, incluindo todos os objetos, são avaliados como verdadeiros quando passados para uma declaração condicional.

- -

Não confunda os valores booleanos primitivos true e false com os valores de true e false do objeto Boolean. Por exemplo:

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

 

- -

Exemplo

- -

No exemplo a seguir, a função verifiqueDados retorna verdadeiro se o número de caracteres em um objeto Text for três; caso contrário, exibe um alerta e retorna falso.

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

Declaração switch

- -

Uma declaração switch permite que um programa avalie uma expressão e tente associar o valor da expressão ao rótulo de um case. Se uma correspondência é encontrada, o programa executa a declaração associada. Uma declaração switch se parece com o seguinte:

- -
switch (expressao) {
-   case rotulo_1:
-      declaracoes_1
-      [break;]
-   case rotulo_2:
-      declaracoes_2
-      [break;]
-   ...
-   default:
-      declaracoes_padrao
-      [break;]
-}
-
- -

O programa primeiramente procura por uma cláusula case com um rótulo que corresponda ao valor da expressão e então transfere o controle para aquela cláusula, executando as declaracoes associadas. Se nenhum rótulo correspondente é encontrado, o programa procura pela cláusula opcional default e, se encontrada, transfere o controle àquela cláusula, executando as declarações associadas. Se nenhuma cláusula default é encontrada, o programa continua a execução a partir da declaracao seguinte ao switch. Por convenção, a cláusula default é a última, mas não é necessário que seja assim.

- -

A instrução break associada a cada cláusula case, garante que o programa sairá do switch assim que a declaração correspondente for executada e que continuará a execução a partir da declaração seguinte ao switch. Se a declaração break for omitida, o programa continua a execução a partir da próxima declaração dentro do switch.

- -

Exemplo

- -

No exemplo a seguir, se tipofruta for avaliada como "Banana", o programa faz a correspondência do valor com case "Banana" e executa a declaração associada. Quando o break é encontrado, o programa termina o switch e executa a declaração seguinte ao condicional. Se o break fosse omitido, a declaração de case "Cereja" também seria executada.

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

Declarações de Manipulação de Error

- -

Você pode chamar uma exceção usando a declaração throw e manipulá-la usando a declaração try...catch.

- - - -

Tipos de exceções

- -

Praticamente pode-se utilizar throw em qualquer objeto de JavaScript. Todavia, nem todos os objetos ativados por throw são igualmente criados. Embora seja bastante comum tratar números ou strings como erros usando throw, é frequentemente mais eficiente usar alguns tipos de exceções especificamente criadas para esses propósitos:

- - - -

Declaração throw

- -

Use a declaração throw para lançar uma exceção. Quando você lança uma exceção, você especifica a expressão contendo o valor a ser lançado:

- -
throw expressão;
-
- -

Você pode lançar qualquer expressão, não apenas expressões de um tipo específico. O código a seguir lança várias exceções de diferentes tipos:

- -
throw "Error2";   // tipo string
-throw 42;         // tipo numérico
-throw true;       // tipo booleano
-throw {toString: function() { return "Eu sou um objeto!"; } };
-
- -
Nota:  Você pode especificar um objeto quando você lança uma exceção. Você pode então, referenciar as propriedades de um objeto no bloco catch.  O exemplo a seguir cria um objeto myUserException do tipo userException e o usa em uma declaração throw.
- -
// Cria um objeto do tipo UserException
-function UserException(mensagem) {
-  this.mensagem = mensagem;
-  this.nome = "UserException";
-}
-
-// Realiza a conversão da exceção para uma string adequada quando usada como uma string.
-// (ex. pelo console de erro)
-UserException.prototype.toString = function() {
-  return this.name + ': "' + this.message + '"';
-}
-
-// Cria uma instância de um tipo de objeto e lança ela
-throw new UserException("Valor muito alto");
- -

Declaração try...catch

- -

A declaração try...catch coloca um bloco de declarações em try, e especifica uma ou mais respostas para uma exceção lançada. Se uma exceção é lançada, a declaração try...catch pegá-a.

- -

A declaração try...catch é composta por um bloco try, que contém uma ou mais declarações, e zero ou mais blocos catch, contendo declarações que especificam o que fazer se uma exceção é lançada no bloco try. Ou seja, você deseja que o bloco try  tenha sucesso, e se ele não tiver êxito, você quer o controle passado para o bloco catch. Se qualquer declaração do bloco try (ou em uma função chamada dentro do bloco try) lança uma exceção, o controle é imediatamente mudado para o bloco catch. Se nenhuma exceção é lançada no bloco try, o bloco catch é ignorado. O bloco finally executa após os blocos try e catch executarem, mas antes das declarações seguinte ao bloco try...catch.

- -

O exemplo a seguir usa a declaração try...catch. O exemplo chama uma função que recupera o nome de um mês no array com base no valor passado para a função. Se o valor não corresponde ao número de um mês (1-12), uma exceção é lançada com o valor "InvalidMonthNo" e as declarações no bloco catch define a váriavel monthName para unknown.

- -
function getMonthName(mo) {
-  mo = mo - 1; // Ajusta o número do mês para o índice do array (1 = Jan, 12 = Dec)
-  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul",
-                "Aug","Sep","Oct","Nov","Dec"];
-  if (months[mo]) {
-    return months[mo];
-  } else {
-    throw "InvalidMonthNo"; //lança uma palavra-chave aqui usada.
-  }
-}
-
-try { // statements to try
-  monthName = getMonthName(myMonth); // função poderia lançar uma exceção
-}
-catch (e) {
-  monthName = "unknown";
-  logMyErrors(e); // passa a exceção para o manipulador de erro -> sua função local.
-}
-
- -

O bloco catch

- -

Você pode usar um bloco catch para lidar com todas as exceções que podem ser geradas no bloco try.

- -
catch (catchID) {
-  declaracoes
-}
-
- -

O bloco catch específica um identificador (catchID na sintaxe anterior), que contém o valor especificado pela declaração throw; você pode usar esse identificador para obter informações sobre a exceção que foi lançada. JavaScript cria este identificador quando o bloco catch é inserido; o identificador dura enquanto o bloco catch está em execução, depois que termina a execução do bloco catch, o identificador não estará mais disponível.

- -

Por exemplo, o seguinte código lança uma exceção. Quando a exceção ocorre, o controle é transferido para o bloco catch.

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

O bloco finally

- -

O bloco finally contém instruções para executar após os blocos try e catch, mas antes das declarações seguinte a declaração try...catch. O bloco finally é executado com ou sem o lançamento de uma exceção. Se uma exceção é lançada, a declaração no bloco finally executa, mesmo que nenhum bloco catch processe a exceção.

- -

Você pode usar bloco finally para deixar a falha de seu script agradável quando uma exceção ocorre; por exemplo, você pode precisar liberar um recurso que seu script tem amarrado. O exemplo a seguir abre um arquivo e então executa instruções que usam o arquivo (JavaScript do lado do servidor permite que você acesse arquivos). Se um exceção é lançada enquanto o arquivo é aberto, o bloco finally fecha o arquivo antes do script falhar.

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

Se o bloco finally retornar um valor, este valor se torna o valor de toda a entrada try-catch-finally, independente de quaisquer declarações de retorno nos blocos try e catch:

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

Substituições de valores de retorno pelo bloco finally também se aplica a exceções lançadas ou re-lançadas dentro do bloco catch:

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

Aninhando declarações try...catch

- -

Você pode aninhar uma ou mais declarações try...catch. Se uma declaração try...catch interior não tem um bloco catch, o delimitador do bloco try...catch da declaração catch é verificado por uma correspondência.

- -

Utilizando objetos de erro

- -

Dependendo do tipo de erro, você pode ser capaz de usar as propriedade 'name' e 'message' para pegar uma mensagem mais refinada. A propriedade 'name' fornece a classe geral de erro (ex., 'DOMException' ou 'Error'), enquanto 'message' geralmente oferece uma mensagem mais sucinta do que se poderia obter através da conversão do objeto de erro para uma string.

- -

Se você está lançando suas próprias exceções, a fim de tirar proveito dessas propriedades (como o seu bloco catch não discrimina entre suas próprias exceções e as exceções próprias da linguagem), você pode usar o construtor Error. Por exemplo:

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

Promises

- -

Começando com ECMAScript 6, JavaScript ganha suporte para objetos {{jsxref("Promise")}} que lhe permite controlar o fluxo de operações diferídas e assíncronas.

- -

Uma Promise assume um destes estados:

- - - -

- -

Carregando uma imagem com XHR

- -

Um exemplo simples usando Promise e XMLHttpRequest para carregar uma imagem disponível no repositório MDN GitHub promise-test. Você também pode vê-lo executando. Cada etapa está comentada o que lhe permite seguir de perto a arquitetura Promise e arquitetura XHR. Aqui está a versão não comentada, mostrando o fluxo Promise para que você possa ter uma ideia:

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

Para uma informação mais detalhada, consulte a página de referência {{jsxref("Promise")}}.

- -
{{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}
diff --git a/files/pt-br/web/javascript/guide/details_of_the_object_model/index.html b/files/pt-br/web/javascript/guide/details_of_the_object_model/index.html new file mode 100644 index 0000000000..55a4c928a5 --- /dev/null +++ b/files/pt-br/web/javascript/guide/details_of_the_object_model/index.html @@ -0,0 +1,705 @@ +--- +title: Detalhes do modelo de objeto +slug: Web/JavaScript/Guide/Detalhes_do_Modelo_do_Objeto +tags: + - Entidade + - Modelo + - Objeto + - Orientação á Objeto +translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model +--- +

JavaScript é uma linguagem orientada a objetos com base em protótipos, em vez de ser baseada em classes. Devido a essa base diferente, pode ser menos evidente como o JavaScript permite criar hierarquias de objetos e ter herança de propriedades e seus valores. Este capítulo tenta esclarecer essa situação.

+ +
+
Este capítulo assume que você já está um pouco familiarizado com JavaScript e que você já tenha usado funções JavaScript para criar simples objetos.
+ +
+
+ +

Linguagens baseada em classe vs. baseada em protótipo

+ +

Linguagens orientadas a objetos baseadas em classe, como Java e C + +, são fundadas no conceito de duas entidades distintas: classes e instâncias.

+ + + +

Uma linguagem baseada em protótipo, como JavaScript, não faz essa distinção: ele simplesmente tem objetos. Uma linguagem baseada em protótipo tem a idéia de um objeto prototípico, um objeto usado como um modelo do qual obtém as propriedades iniciais para um novo objeto. Qualquer objeto pode especificar suas próprias propriedades, quando você o cria ou em tempo de execução. Além disso, qualquer objeto pode ser associado como um protótipo de outro objeto, permitindo ao segundo objeto compartilhar as propriedades do primeiro objeto.

+ +

Definindo uma classe

+ +

Em linguagens baseadas em classe, você define uma classe em uma definição de classe separada. Nessa definição, você pode especificar métodos especiais, chamados de construtores, para criar instâncias da classe. Um método construtor pode especificar valores iniciais para as propriedades da instância e executar outros processamentos apropriados no momento da criação. Você pode usar o operador new, em associação com o método construtor para criar instâncias de classe.

+ +

O JavaScript segue um modelo semelhante, mas não têm uma definição da classe separada do construtor. Em vez disso, você define uma função de construtor para criar objetos com um conjunto inicial particular de propriedades e valores. Qualquer função JavaScript pode ser usado como um construtor. Você pode usar o operador new com uma função de construtor para criar um novo objeto.

+ +

Subclasses e herança

+ +

Em uma linguagem baseada em classe, você cria a hierárquia de classes através de sua definição. Em uma definição de classes,  você pode  especificar que a nova classe é uma subclasse de outra já existente. A subclasse herda todas as propriedades da  superclasse e pode adicionar novas propriedades ou modificar propriedades herdadas. Por exemplo, assuma que  a classe Employee tem somente duas propriedades name e dept , e Manager é uma subclasse of Employee que adiciona a propriedade reports. Neste caso, uma instância da classe Manager  terá todas as três propiedades: name, dept, and reports.

+ +

Em JavaScript, a herança é implementada associando um objeto prototípico a qualquer função de construtor. Então, você pode criar exatamente o mesmo exemplo: EmployeeManager, mas utilizando uma terminologia ligeramente diferente. Primeiro, define-se a função de construtor de  Employee, especificando as propriedades name e dept. Depois,  define-se a função de construtor de  Manager, especificando a propriedade reports. Finalmente, associa-se um objeto new Employee  como  prototype para a função de construtor Manager. Então, quando vocẽ criar um objeto new Manager, ele herdará as propriedades  name e dept do objeto Employee.

+ +

Adicionando e removendo propriedades

+ +

Em uma linguagem baseada em classe, você normalmente cria uma classe em tempo de compilação e então vincula as instâncias da classe em tempo de compilação, ou tempo de execução. Você não pode alterar o número ou o tipo de propriedade de uma classe após definí-la. Em javaScript, no entanto, você pode adicionar ou remover propriedades de qualquer objeto. Se você adiciona uma propriedade a um objeto que é usado como o protótipo para um conjunto de objetos, os objetos no qual ele é protótipo herdarão as novas propriedades.

+ +

Sumário das diferenças

+ +

A tabela a seguir apresenta um breve resumo de algumas dessas diferenças. O restante deste capítulo descreve os detalhes do uso de construtores e protótipos JavaScript para criar uma hierarquia de objetos e compara isso à maneira como você faria em Java.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Comparação de objetos do sistema baseados em classes (Java) e baseado em protótipo (JavaScript)
Baseados em classes (Java)Baseados em protótipos (JavaScript)
Classes e instancias são entidades distintas.Todos os objetos são instancias.
Define uma classe com uma definição de classe; cria um objeto - como instância da classe - com o método constructor.Define e cria um conjunto de objetos com funções construtoras.
Cria um único objeto com o operador new.Faz o mesmo.
Constroi uma hierarquia de objetos usando definição de classe para definir subclasses de classes existentes.Constrói uma hierarquia de objetos, atribuindo um objeto como o protótipo associado com uma função de construtor.
Herda propriedade seguindo a cadeia de classe.Herda propriedade seguindo a cadeia de protótipo.
Definição de classe especifica todas as propriedades de todas as instâncias de uma classe. Não é possível adicionar propriedades dinamicamente em tempo de execução.Função construtor ou protótipo especifica um conjunto inicial de propriedades. Pode adicionar ou remover propriedades de forma dinâmica para objetos individuais ou para todo o conjunto de objetos.
+ +

O exemplo employee

+ +

O restante deste capítulo usa a hierarquia employee como mostrado na figura abaixo. 

+ +
+

Uma simples hierarquia de objetos:

+ +

+ + +
+ +

Criando a hierarquia

+ +

Há muitas formas de definir funções construtoras apropriadas para implementar a hierarquia Employee. Como escolher defini-las depende amplamente do que você quer ser capaz de fazer em sua aplicação.

+ +

Esta seção mostra definições simples de como trabalhar com heranças. Nestas definições, você não pode especificar nenhum valor de propriedade quando criar um objeto. O recém-criado objeto terá os valores padrão, que você poderá alterar mais tarde.

+ +

Na aplicação real, você poderia definir construtores que permitem que você forneça valores de propriedade no momento da criação do objeto (veja Construtores flexíveis para saber mais). Por enquanto, estas simples definições demonstram como a herança ocorre.

+ +

As seguintes definições Java e JavaScript Employee são similares. A única diferença é que você precisa especificar o tipo de cada propriedade em Java, mas não em JavaScript (devido ao Java ser uma linguagem fortemente tipada enquanto o JavaScript é linguagem fracamente tipada).

+ +
+

JavaScript

+ +
function Employee() {
+  this.name = "";
+  this.dept = "general";
+}
+
+ +

Java

+ +
public class Employee {
+   public String name = "";
+   public String dept = "general";
+}
+
+
+ +

As definições Manager e WorkerBee mostram a diferença na forma de especificar o próximo objeto mais alto na cadeia de herança. Em JavaScript, você adiciona uma instância prototípica como o valor da propriedade prototype da função construtora. Você pode fazer isso a qualquer momento depois de definir o construtor. Em Java, você especifica a superclasse dentro da classe definida. Você não pode alterar a superclasse fora da classe definida.

+ +
+

JavaScript

+ +
function Manager() {
+  Employee.call(this);
+  this.reports = [];
+}
+Manager.prototype = Object.create(Employee.prototype);
+
+function WorkerBee() {
+  Employee.call(this);
+  this.projects = [];
+}
+WorkerBee.prototype = Object.create(Employee.prototype);
+
+ +

Java

+ +
public class Manager extends Employee {
+   public Employee[] reports = new Employee[0];
+}
+
+
+
+public class WorkerBee extends Employee {
+   public String[] projects = new String[0];
+}
+
+
+
+
+ +

As definições Engineer e SalesPerson criam objetos que descendem de WorkerBee e consequentemente de Employee. Objetos destes tipos tem propriedades de todos os objetos acima de sua cadeia. Em adição, estas definições substituem o valor herdado da propriedade dept com novos valores específicos para esses objetos.

+ +
+

JavaScript

+ +
function SalesPerson() {
+   WorkerBee.call(this);
+   this.dept = "sales";
+   this.quota = 100;
+}
+SalesPerson.prototype = Object.create(WorkerBee.prototype);
+
+function Engineer() {
+   WorkerBee.call(this);
+   this.dept = "engineering";
+   this.machine = "";
+}
+Engineer.prototype = Object.create(WorkerBee.prototype);
+
+ +

Java

+ +
public class SalesPerson extends WorkerBee {
+   public double quota;
+   public dept = "sales";
+   public quota = 100.0;
+}
+
+
+public class Engineer extends WorkerBee {
+   public String machine;
+   public dept = "engineering";
+   public machine = "";
+}
+
+
+
+ +

Usando estas definições, você pode criar instâncias desses objetos que obterão valores padrão para suas propriedades. A próxima imagem mostra o uso destas definições JavaScript para criar novos objetos e mostrar os valores das propriedades dos novos objetos. 

+ +
+

Note: O termo instancia   tem significado específicamente técnico em linguagens baseadas em classe. Nessas linguagens, uma instância é uma instanciação individual de uma classe e é fundamentalmente diferente de uma classe. Em JavaScript, "instância" não tem esse significado técnico porque JavaScript não tem essa diferença entre classes e instâncias. No entanto, falando sobre JavaScript, "instância" pode ser usada informalmente para significar um objeto criado usando uma função construtora particular. Então, neste exemplo, você pode informalmente dizer que jane é uma instância de Engineer. Similarmente, embora os termos parent, child, ancestor, e descendant não tenham significados formais em JavaScript; você pode usá-los informalmente para referir a objetos altos ou baixos na cadeia de protótipos.

+
+ +

Criando objetos com definições simples

+ +
+

Hierarquia do Objeto

+ +

A hierarquia abaixo foi criada utilizando o código ao lado.

+ +

+ +

Objetos individuais = Jim, Sally, Mark, Fred, Jane, etc. "Instancias" criadas a partir do construtor.

+ +
var jim = new Employee;
+// jim.name is ''
+// jim.dept is 'general'
+
+var sally = new Manager;
+// sally.name is ''
+// sally.dept is 'general'
+// sally.reports is []
+
+var mark = new WorkerBee;
+// mark.name is ''
+// mark.dept is 'general'
+// mark.projects is []
+
+var fred = new SalesPerson;
+// fred.name is ''
+// fred.dept is 'sales'
+// fred.projects is []
+// fred.quota is 100
+
+var jane = new Engineer;
+// jane.name is ''
+// jane.dept is 'engineering'
+// jane.projects is []
+// jane.machine is ''
+
+
+ +

Propriedades do Objeto

+ +

Esta seção discute como objetos herdam propriedades de outros objetos na cadeia de protótipos e o que acontece quando você adiciona uma propriedade em tempo de execução.

+ +

Herdando Propriedades

+ +

Suponha que você criou o objeto mark como um WorkerBee com a seguinte declaração:

+ +
var mark = new WorkerBee;
+
+ +

Quando o JavaScript vê o operador new, ele cria um novo objeto genérico e implicitamente define o valor da propriedade interna [[Protótipo]] para o valor de WorkerBee.prototype passando este novo objeto como o valor da palavra-chave this para a função construtora de WorkerBee. A propriedade interna [[__proto__]] determina a cadeia de protótipos usada para retornar os valores das propriedades. Uma vez que essas propriedades são definidas, o JavaScript retorna o novo objeto e a declaração de atribuição define a variável mark para este objeto.

+ +

Este processo não põe explicitamente valores no objeto mark (valores locais) para as propriedades que mark herdou da cadeia de protótipo. Quando você solicita o valor de uma propriedade, o JavaScript primeiro verifica se o valor existe nesse objeto. Caso exista, esse valor é retornado. Se o valor não existe localmente, JavaScript verifica a cadeia de protótipos (usando a propriedade  interna __proto__). Se um objeto na cadeia de protótipos possui um valor para a propriedade, este valor é retornado. Se nenhuma propriedade é encontrada, o Javascript avisa que o objeto não possui a propriedade. Deste modo, o objeto mark possui as seguintes propriedades e valores: 

+ +
mark.name = "";
+mark.dept = "general";
+mark.projects = [];
+
+ +

The mark object inherits values for the name and dept properties from the prototypical object in mark.__proto__. It is assigned a local value for the projects property by the WorkerBee constructor. This gives you inheritance of properties and their values in JavaScript. Some subtleties of this process are discussed in Property inheritance revisited.

+ +

Because these constructors do not let you supply instance-specific values, this information is generic. The property values are the default ones shared by all new objects created from WorkerBee. You can, of course, change the values of any of these properties. So, you could give specific information for mark as follows:

+ +
mark.name = "Doe, Mark";
+mark.dept = "admin";
+mark.projects = ["navigator"];
+ +

Adding properties

+ +

In JavaScript, you can add properties to any object at run time. You are not constrained to use only the properties provided by the constructor function. To add a property that is specific to a single object, you assign a value to the object, as follows:

+ +
mark.bonus = 3000;
+
+ +

Now, the mark object has a bonus property, but no other WorkerBee has this property.

+ +

If you add a new property to an object that is being used as the prototype for a constructor function, you add that property to all objects that inherit properties from the prototype. For example, you can add a specialty property to all employees with the following statement:

+ +
Employee.prototype.specialty = "none";
+
+ +

As soon as JavaScript executes this statement, the mark object also has the specialty property with the value of "none". The following figure shows the effect of adding this property to the Employee prototype and then overriding it for the Engineer prototype.

+ +


+ Adding properties

+ +

More flexible constructors

+ +

The constructor functions shown so far do not let you specify property values when you create an instance. As with Java, you can provide arguments to constructors to initialize property values for instances. The following figure shows one way to do this.

+ +


+ Specifying properties in a constructor, take 1

+ +

The following table shows the Java and JavaScript definitions for these objects.

+ +
+

JavaScript

+ +

Java

+
+ +
+
function Employee (name, dept) {
+  this.name = name || "";
+  this.dept = dept || "general";
+}
+
+ +
public class Employee {
+   public String name;
+   public String dept;
+   public Employee () {
+      this("", "general");
+   }
+   public Employee (String name) {
+      this(name, "general");
+   }
+   public Employee (String name, String dept) {
+      this.name = name;
+      this.dept = dept;
+   }
+}
+
+
+ +
+
function WorkerBee (projs) {
+
+ this.projects = projs || [];
+}
+WorkerBee.prototype = new Employee;
+
+ +
public class WorkerBee extends Employee {
+   public String[] projects;
+   public WorkerBee () {
+      this(new String[0]);
+   }
+   public WorkerBee (String[] projs) {
+      projects = projs;
+   }
+}
+
+
+ +
+
+function Engineer (mach) {
+   this.dept = "engineering";
+   this.machine = mach || "";
+}
+Engineer.prototype = new WorkerBee;
+
+ +
public class Engineer extends WorkerBee {
+   public String machine;
+   public Engineer () {
+      dept = "engineering";
+      machine = "";
+   }
+   public Engineer (String mach) {
+      dept = "engineering";
+      machine = mach;
+   }
+}
+
+
+ +

These JavaScript definitions use a special idiom for setting default values:

+ +
this.name = name || "";
+
+ +

The JavaScript logical OR operator (||) evaluates its first argument. If that argument converts to true, the operator returns it. Otherwise, the operator returns the value of the second argument. Therefore, this line of code tests to see if name has a useful value for the name property. If it does, it sets this.name to that value. Otherwise, it sets this.name to the empty string. This chapter uses this idiom for brevity; however, it can be puzzling at first glance.

+ +
+

Note: This may not work as expected if the constructor function is called with arguments which convert to false (like 0 (zero) and empty string (""). In this case the default value will be chosen.

+
+ +

With these definitions, when you create an instance of an object, you can specify values for the locally defined properties. You can use the following statement to create a new Engineer:

+ +
var jane = new Engineer("belau");
+
+ +

Jane's properties are now:

+ +
jane.name == "";
+jane.dept == "engineering";
+jane.projects == [];
+jane.machine == "belau"
+
+ +

Notice that with these definitions, you cannot specify an initial value for an inherited property such as name. If you want to specify an initial value for inherited properties in JavaScript, you need to add more code to the constructor function.

+ +

So far, the constructor function has created a generic object and then specified local properties and values for the new object. You can have the constructor add more properties by directly calling the constructor function for an object higher in the prototype chain. The following figure shows these new definitions.

+ +


+ Specifying properties in a constructor, take 2

+ +

Let's look at one of these definitions in detail. Here's the new definition for the Engineer constructor:

+ +
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+
+ +

Suppose you create a new Engineer object as follows:

+ +
var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
+
+ +

JavaScript follows these steps:

+ +
    +
  1. The new operator creates a generic object and sets its __proto__ property to Engineer.prototype.
  2. +
  3. The new operator passes the new object to the Engineer constructor as the value of the this keyword.
  4. +
  5. The constructor creates a new property called base for that object and assigns the value of the WorkerBee constructor to the base property. This makes the WorkerBee constructor a method of the Engineer object.The name of the base property is not special. You can use any legal property name; base is simply evocative of its purpose.
  6. +
  7. +

    The constructor calls the base method, passing as its arguments two of the arguments passed to the constructor ("Doe, Jane" and ["navigator", "javascript"]) and also the string "engineering". Explicitly using "engineering" in the constructor indicates that all Engineer objects have the same value for the inherited dept property, and this value overrides the value inherited from Employee.

    +
  8. +
  9. Because base is a method of Engineer, within the call to base, JavaScript binds the this keyword to the object created in Step 1. Thus, the WorkerBee function in turn passes the "Doe, Jane" and "engineering" arguments to the Employee constructor function. Upon return from the Employee constructor function, the WorkerBee function uses the remaining argument to set the projects property.
  10. +
  11. Upon return from the base method, the Engineer constructor initializes the object's machine property to "belau".
  12. +
  13. Upon return from the constructor, JavaScript assigns the new object to the jane variable.
  14. +
+ +

You might think that, having called the WorkerBee constructor from inside the Engineer constructor, you have set up inheritance appropriately for Engineer objects. This is not the case. Calling the WorkerBee constructor ensures that an Engineer object starts out with the properties specified in all constructor functions that are called. However, if you later add properties to the Employee or WorkerBee prototypes, those properties are not inherited by the Engineer object. For example, assume you have the following statements:

+ +
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
+Employee.prototype.specialty = "none";
+
+ +

The jane object does not inherit the specialty property. You still need to explicitly set up the prototype to ensure dynamic inheritance. Assume instead you have these statements:

+ +
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+Engineer.prototype = new WorkerBee;
+var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
+Employee.prototype.specialty = "none";
+
+ +

Now the value of the jane object's specialty property is "none".

+ +

Another way of inheriting is by using the call() / apply() methods. Below are equivalent:

+ +
+
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+
+ +
function Engineer (name, projs, mach) {
+  WorkerBee.call(this, name, "engineering", projs);
+  this.machine = mach || "";
+}
+
+
+ +

Using the javascript call() method makes a cleaner implementation because the base is not needed anymore.

+ +

Property inheritance revisited

+ +

The preceding sections described how JavaScript constructors and prototypes provide hierarchies and inheritance. This section discusses some subtleties that were not necessarily apparent in the earlier discussions.

+ +

Local versus inherited values

+ +

When you access an object property, JavaScript performs these steps, as described earlier in this chapter:

+ +
    +
  1. Check to see if the value exists locally. If it does, return that value.
  2. +
  3. If there is not a local value, check the prototype chain (using the __proto__ property).
  4. +
  5. If an object in the prototype chain has a value for the specified property, return that value.
  6. +
  7. If no such property is found, the object does not have the property.
  8. +
+ +

The outcome of these steps depends on how you define things along the way. The original example had these definitions:

+ +
function Employee () {
+  this.name = "";
+  this.dept = "general";
+}
+
+function WorkerBee () {
+  this.projects = [];
+}
+WorkerBee.prototype = new Employee;
+
+ +

With these definitions, suppose you create amy as an instance of WorkerBee with the following statement:

+ +
var amy = new WorkerBee;
+
+ +

The amy object has one local property, projects. The values for the name and dept properties are not local to amy and so are gotten from the amy object's __proto__ property. Thus, amy has these property values:

+ +
amy.name == "";
+amy.dept == "general";
+amy.projects == [];
+
+ +

Now suppose you change the value of the name property in the prototype associated with Employee:

+ +
Employee.prototype.name = "Unknown"
+
+ +

At first glance, you might expect that new value to propagate down to all the instances of Employee. However, it does not.

+ +

When you create any instance of the Employee object, that instance gets a local value for the name property (the empty string). This means that when you set the WorkerBee prototype by creating a new Employee object, WorkerBee.prototype has a local value for the name property. Therefore, when JavaScript looks up the name property of the amy object (an instance of WorkerBee), JavaScript finds the local value for that property in WorkerBee.prototype. It therefore does not look farther up the chain to Employee.prototype.

+ +

If you want to change the value of an object property at run time and have the new value be inherited by all descendants of the object, you cannot define the property in the object's constructor function. Instead, you add it to the constructor's associated prototype. For example, assume you change the preceding code to the following:

+ +
function Employee () {
+  this.dept = "general";
+}
+Employee.prototype.name = "";
+
+function WorkerBee () {
+  this.projects = [];
+}
+WorkerBee.prototype = new Employee;
+
+var amy = new WorkerBee;
+
+Employee.prototype.name = "Unknown";
+
+ +

In this case, the name property of amy becomes "Unknown".

+ +

As these examples show, if you want to have default values for object properties and you want to be able to change the default values at run time, you should set the properties in the constructor's prototype, not in the constructor function itself.

+ +

Determining instance relationships

+ +

Property lookup in JavaScript looks within an object's own properties and, if the property name is not found, it looks within the special object property __proto__. This continues recursively; the process is called "lookup in the prototype chain".

+ +

The special property __proto__ is set when an object is constructed; it is set to the value of the constructor's prototype property. So the expression new Foo() creates an object with __proto__ == Foo.prototype. Consequently, changes to the properties of Foo.prototype alters the property lookup for all objects that were created by new Foo().

+ +

Every object has a __proto__ object property (except Object); every function has a prototype object property. So objects can be related by 'prototype inheritance' to other objects. You can test for inheritance by comparing an object's __proto__ to a function's prototype object. JavaScript provides a shortcut: the instanceof operator tests an object against a function and returns true if the object inherits from the function prototype. For example,

+ +
var f = new Foo();
+var isTrue = (f instanceof Foo);
+ +

For a more detailed example, suppose you have the same set of definitions shown in Inheriting properties. Create an Engineer object as follows:

+ +
var chris = new Engineer("Pigman, Chris", ["jsd"], "fiji");
+
+ +

With this object, the following statements are all true:

+ +
chris.__proto__ == Engineer.prototype;
+chris.__proto__.__proto__ == WorkerBee.prototype;
+chris.__proto__.__proto__.__proto__ == Employee.prototype;
+chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype;
+chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
+
+ +

Given this, you could write an instanceOf function as follows:

+ +
function instanceOf(object, constructor) {
+   object = object.__proto__;
+   while (object != null) {
+      if (object == constructor.prototype)
+         return true;
+      if (typeof object == 'xml') {
+        return constructor.prototype == XML.prototype;
+      }
+      object = object.__proto__;
+   }
+   return false;
+}
+
+ +
Note: The implementation above checks the type of the object against "xml" in order to work around a quirk of how XML objects are represented in recent versions of JavaScript. See {{ bug(634150) }} if you want the nitty-gritty details.
+ +

Using the instanceOf function defined above, these expressions are true:

+ +
instanceOf (chris, Engineer)
+instanceOf (chris, WorkerBee)
+instanceOf (chris, Employee)
+instanceOf (chris, Object)
+
+ +

But the following expression is false:

+ +
instanceOf (chris, SalesPerson)
+
+ +

Global information in constructors

+ +

When you create constructors, you need to be careful if you set global information in the constructor. For example, assume that you want a unique ID to be automatically assigned to each new employee. You could use the following definition for Employee:

+ +
var idCounter = 1;
+
+function Employee (name, dept) {
+   this.name = name || "";
+   this.dept = dept || "general";
+   this.id = idCounter++;
+}
+
+ +

With this definition, when you create a new Employee, the constructor assigns it the next ID in sequence and then increments the global ID counter. So, if your next statement is the following, victoria.id is 1 and harry.id is 2:

+ +
var victoria = new Employee("Pigbert, Victoria", "pubs")
+var harry = new Employee("Tschopik, Harry", "sales")
+
+ +

At first glance that seems fine. However, idCounter gets incremented every time an Employee object is created, for whatever purpose. If you create the entire Employee hierarchy shown in this chapter, the Employee constructor is called every time you set up a prototype. Suppose you have the following code:

+ +
var idCounter = 1;
+
+function Employee (name, dept) {
+   this.name = name || "";
+   this.dept = dept || "general";
+   this.id = idCounter++;
+}
+
+function Manager (name, dept, reports) {...}
+Manager.prototype = new Employee;
+
+function WorkerBee (name, dept, projs) {...}
+WorkerBee.prototype = new Employee;
+
+function Engineer (name, projs, mach) {...}
+Engineer.prototype = new WorkerBee;
+
+function SalesPerson (name, projs, quota) {...}
+SalesPerson.prototype = new WorkerBee;
+
+var mac = new Engineer("Wood, Mac");
+
+ +

Further assume that the definitions omitted here have the base property and call the constructor above them in the prototype chain. In this case, by the time the mac object is created, mac.id is 5.

+ +

Depending on the application, it may or may not matter that the counter has been incremented these extra times. If you care about the exact value of this counter, one possible solution involves instead using the following constructor:

+ +
function Employee (name, dept) {
+   this.name = name || "";
+   this.dept = dept || "general";
+   if (name)
+      this.id = idCounter++;
+}
+
+ +

When you create an instance of Employee to use as a prototype, you do not supply arguments to the constructor. Using this definition of the constructor, when you do not supply arguments, the constructor does not assign a value to the id and does not update the counter. Therefore, for an Employee to get an assigned id, you must specify a name for the employee. In this example, mac.id would be 1.

+ +

No multiple inheritance

+ +

Some object-oriented languages allow multiple inheritance. That is, an object can inherit the properties and values from unrelated parent objects. JavaScript does not support multiple inheritance.

+ +

Inheritance of property values occurs at run time by JavaScript searching the prototype chain of an object to find a value. Because an object has a single associated prototype, JavaScript cannot dynamically inherit from more than one prototype chain.

+ +

In JavaScript, you can have a constructor function call more than one other constructor function within it. This gives the illusion of multiple inheritance. For example, consider the following statements:

+ +
function Hobbyist (hobby) {
+   this.hobby = hobby || "scuba";
+}
+
+function Engineer (name, projs, mach, hobby) {
+   this.base1 = WorkerBee;
+   this.base1(name, "engineering", projs);
+   this.base2 = Hobbyist;
+   this.base2(hobby);
+   this.machine = mach || "";
+}
+Engineer.prototype = new WorkerBee;
+
+var dennis = new Engineer("Doe, Dennis", ["collabra"], "hugo")
+
+ +

Further assume that the definition of WorkerBee is as used earlier in this chapter. In this case, the dennis object has these properties:

+ +
dennis.name == "Doe, Dennis"
+dennis.dept == "engineering"
+dennis.projects == ["collabra"]
+dennis.machine == "hugo"
+dennis.hobby == "scuba"
+
+ +

So dennis does get the hobby property from the Hobbyist constructor. However, assume you then add a property to the Hobbyist constructor's prototype:

+ +
Hobbyist.prototype.equipment = ["mask", "fins", "regulator", "bcd"]
+
+ +

The dennis object does not inherit this new property.

+ +
{{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}
diff --git a/files/pt-br/web/javascript/guide/detalhes_do_modelo_do_objeto/index.html b/files/pt-br/web/javascript/guide/detalhes_do_modelo_do_objeto/index.html deleted file mode 100644 index 55a4c928a5..0000000000 --- a/files/pt-br/web/javascript/guide/detalhes_do_modelo_do_objeto/index.html +++ /dev/null @@ -1,705 +0,0 @@ ---- -title: Detalhes do modelo de objeto -slug: Web/JavaScript/Guide/Detalhes_do_Modelo_do_Objeto -tags: - - Entidade - - Modelo - - Objeto - - Orientação á Objeto -translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model ---- -

JavaScript é uma linguagem orientada a objetos com base em protótipos, em vez de ser baseada em classes. Devido a essa base diferente, pode ser menos evidente como o JavaScript permite criar hierarquias de objetos e ter herança de propriedades e seus valores. Este capítulo tenta esclarecer essa situação.

- -
-
Este capítulo assume que você já está um pouco familiarizado com JavaScript e que você já tenha usado funções JavaScript para criar simples objetos.
- -
-
- -

Linguagens baseada em classe vs. baseada em protótipo

- -

Linguagens orientadas a objetos baseadas em classe, como Java e C + +, são fundadas no conceito de duas entidades distintas: classes e instâncias.

- - - -

Uma linguagem baseada em protótipo, como JavaScript, não faz essa distinção: ele simplesmente tem objetos. Uma linguagem baseada em protótipo tem a idéia de um objeto prototípico, um objeto usado como um modelo do qual obtém as propriedades iniciais para um novo objeto. Qualquer objeto pode especificar suas próprias propriedades, quando você o cria ou em tempo de execução. Além disso, qualquer objeto pode ser associado como um protótipo de outro objeto, permitindo ao segundo objeto compartilhar as propriedades do primeiro objeto.

- -

Definindo uma classe

- -

Em linguagens baseadas em classe, você define uma classe em uma definição de classe separada. Nessa definição, você pode especificar métodos especiais, chamados de construtores, para criar instâncias da classe. Um método construtor pode especificar valores iniciais para as propriedades da instância e executar outros processamentos apropriados no momento da criação. Você pode usar o operador new, em associação com o método construtor para criar instâncias de classe.

- -

O JavaScript segue um modelo semelhante, mas não têm uma definição da classe separada do construtor. Em vez disso, você define uma função de construtor para criar objetos com um conjunto inicial particular de propriedades e valores. Qualquer função JavaScript pode ser usado como um construtor. Você pode usar o operador new com uma função de construtor para criar um novo objeto.

- -

Subclasses e herança

- -

Em uma linguagem baseada em classe, você cria a hierárquia de classes através de sua definição. Em uma definição de classes,  você pode  especificar que a nova classe é uma subclasse de outra já existente. A subclasse herda todas as propriedades da  superclasse e pode adicionar novas propriedades ou modificar propriedades herdadas. Por exemplo, assuma que  a classe Employee tem somente duas propriedades name e dept , e Manager é uma subclasse of Employee que adiciona a propriedade reports. Neste caso, uma instância da classe Manager  terá todas as três propiedades: name, dept, and reports.

- -

Em JavaScript, a herança é implementada associando um objeto prototípico a qualquer função de construtor. Então, você pode criar exatamente o mesmo exemplo: EmployeeManager, mas utilizando uma terminologia ligeramente diferente. Primeiro, define-se a função de construtor de  Employee, especificando as propriedades name e dept. Depois,  define-se a função de construtor de  Manager, especificando a propriedade reports. Finalmente, associa-se um objeto new Employee  como  prototype para a função de construtor Manager. Então, quando vocẽ criar um objeto new Manager, ele herdará as propriedades  name e dept do objeto Employee.

- -

Adicionando e removendo propriedades

- -

Em uma linguagem baseada em classe, você normalmente cria uma classe em tempo de compilação e então vincula as instâncias da classe em tempo de compilação, ou tempo de execução. Você não pode alterar o número ou o tipo de propriedade de uma classe após definí-la. Em javaScript, no entanto, você pode adicionar ou remover propriedades de qualquer objeto. Se você adiciona uma propriedade a um objeto que é usado como o protótipo para um conjunto de objetos, os objetos no qual ele é protótipo herdarão as novas propriedades.

- -

Sumário das diferenças

- -

A tabela a seguir apresenta um breve resumo de algumas dessas diferenças. O restante deste capítulo descreve os detalhes do uso de construtores e protótipos JavaScript para criar uma hierarquia de objetos e compara isso à maneira como você faria em Java.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Comparação de objetos do sistema baseados em classes (Java) e baseado em protótipo (JavaScript)
Baseados em classes (Java)Baseados em protótipos (JavaScript)
Classes e instancias são entidades distintas.Todos os objetos são instancias.
Define uma classe com uma definição de classe; cria um objeto - como instância da classe - com o método constructor.Define e cria um conjunto de objetos com funções construtoras.
Cria um único objeto com o operador new.Faz o mesmo.
Constroi uma hierarquia de objetos usando definição de classe para definir subclasses de classes existentes.Constrói uma hierarquia de objetos, atribuindo um objeto como o protótipo associado com uma função de construtor.
Herda propriedade seguindo a cadeia de classe.Herda propriedade seguindo a cadeia de protótipo.
Definição de classe especifica todas as propriedades de todas as instâncias de uma classe. Não é possível adicionar propriedades dinamicamente em tempo de execução.Função construtor ou protótipo especifica um conjunto inicial de propriedades. Pode adicionar ou remover propriedades de forma dinâmica para objetos individuais ou para todo o conjunto de objetos.
- -

O exemplo employee

- -

O restante deste capítulo usa a hierarquia employee como mostrado na figura abaixo. 

- -
-

Uma simples hierarquia de objetos:

- -

- - -
- -

Criando a hierarquia

- -

Há muitas formas de definir funções construtoras apropriadas para implementar a hierarquia Employee. Como escolher defini-las depende amplamente do que você quer ser capaz de fazer em sua aplicação.

- -

Esta seção mostra definições simples de como trabalhar com heranças. Nestas definições, você não pode especificar nenhum valor de propriedade quando criar um objeto. O recém-criado objeto terá os valores padrão, que você poderá alterar mais tarde.

- -

Na aplicação real, você poderia definir construtores que permitem que você forneça valores de propriedade no momento da criação do objeto (veja Construtores flexíveis para saber mais). Por enquanto, estas simples definições demonstram como a herança ocorre.

- -

As seguintes definições Java e JavaScript Employee são similares. A única diferença é que você precisa especificar o tipo de cada propriedade em Java, mas não em JavaScript (devido ao Java ser uma linguagem fortemente tipada enquanto o JavaScript é linguagem fracamente tipada).

- -
-

JavaScript

- -
function Employee() {
-  this.name = "";
-  this.dept = "general";
-}
-
- -

Java

- -
public class Employee {
-   public String name = "";
-   public String dept = "general";
-}
-
-
- -

As definições Manager e WorkerBee mostram a diferença na forma de especificar o próximo objeto mais alto na cadeia de herança. Em JavaScript, você adiciona uma instância prototípica como o valor da propriedade prototype da função construtora. Você pode fazer isso a qualquer momento depois de definir o construtor. Em Java, você especifica a superclasse dentro da classe definida. Você não pode alterar a superclasse fora da classe definida.

- -
-

JavaScript

- -
function Manager() {
-  Employee.call(this);
-  this.reports = [];
-}
-Manager.prototype = Object.create(Employee.prototype);
-
-function WorkerBee() {
-  Employee.call(this);
-  this.projects = [];
-}
-WorkerBee.prototype = Object.create(Employee.prototype);
-
- -

Java

- -
public class Manager extends Employee {
-   public Employee[] reports = new Employee[0];
-}
-
-
-
-public class WorkerBee extends Employee {
-   public String[] projects = new String[0];
-}
-
-
-
-
- -

As definições Engineer e SalesPerson criam objetos que descendem de WorkerBee e consequentemente de Employee. Objetos destes tipos tem propriedades de todos os objetos acima de sua cadeia. Em adição, estas definições substituem o valor herdado da propriedade dept com novos valores específicos para esses objetos.

- -
-

JavaScript

- -
function SalesPerson() {
-   WorkerBee.call(this);
-   this.dept = "sales";
-   this.quota = 100;
-}
-SalesPerson.prototype = Object.create(WorkerBee.prototype);
-
-function Engineer() {
-   WorkerBee.call(this);
-   this.dept = "engineering";
-   this.machine = "";
-}
-Engineer.prototype = Object.create(WorkerBee.prototype);
-
- -

Java

- -
public class SalesPerson extends WorkerBee {
-   public double quota;
-   public dept = "sales";
-   public quota = 100.0;
-}
-
-
-public class Engineer extends WorkerBee {
-   public String machine;
-   public dept = "engineering";
-   public machine = "";
-}
-
-
-
- -

Usando estas definições, você pode criar instâncias desses objetos que obterão valores padrão para suas propriedades. A próxima imagem mostra o uso destas definições JavaScript para criar novos objetos e mostrar os valores das propriedades dos novos objetos. 

- -
-

Note: O termo instancia   tem significado específicamente técnico em linguagens baseadas em classe. Nessas linguagens, uma instância é uma instanciação individual de uma classe e é fundamentalmente diferente de uma classe. Em JavaScript, "instância" não tem esse significado técnico porque JavaScript não tem essa diferença entre classes e instâncias. No entanto, falando sobre JavaScript, "instância" pode ser usada informalmente para significar um objeto criado usando uma função construtora particular. Então, neste exemplo, você pode informalmente dizer que jane é uma instância de Engineer. Similarmente, embora os termos parent, child, ancestor, e descendant não tenham significados formais em JavaScript; você pode usá-los informalmente para referir a objetos altos ou baixos na cadeia de protótipos.

-
- -

Criando objetos com definições simples

- -
-

Hierarquia do Objeto

- -

A hierarquia abaixo foi criada utilizando o código ao lado.

- -

- -

Objetos individuais = Jim, Sally, Mark, Fred, Jane, etc. "Instancias" criadas a partir do construtor.

- -
var jim = new Employee;
-// jim.name is ''
-// jim.dept is 'general'
-
-var sally = new Manager;
-// sally.name is ''
-// sally.dept is 'general'
-// sally.reports is []
-
-var mark = new WorkerBee;
-// mark.name is ''
-// mark.dept is 'general'
-// mark.projects is []
-
-var fred = new SalesPerson;
-// fred.name is ''
-// fred.dept is 'sales'
-// fred.projects is []
-// fred.quota is 100
-
-var jane = new Engineer;
-// jane.name is ''
-// jane.dept is 'engineering'
-// jane.projects is []
-// jane.machine is ''
-
-
- -

Propriedades do Objeto

- -

Esta seção discute como objetos herdam propriedades de outros objetos na cadeia de protótipos e o que acontece quando você adiciona uma propriedade em tempo de execução.

- -

Herdando Propriedades

- -

Suponha que você criou o objeto mark como um WorkerBee com a seguinte declaração:

- -
var mark = new WorkerBee;
-
- -

Quando o JavaScript vê o operador new, ele cria um novo objeto genérico e implicitamente define o valor da propriedade interna [[Protótipo]] para o valor de WorkerBee.prototype passando este novo objeto como o valor da palavra-chave this para a função construtora de WorkerBee. A propriedade interna [[__proto__]] determina a cadeia de protótipos usada para retornar os valores das propriedades. Uma vez que essas propriedades são definidas, o JavaScript retorna o novo objeto e a declaração de atribuição define a variável mark para este objeto.

- -

Este processo não põe explicitamente valores no objeto mark (valores locais) para as propriedades que mark herdou da cadeia de protótipo. Quando você solicita o valor de uma propriedade, o JavaScript primeiro verifica se o valor existe nesse objeto. Caso exista, esse valor é retornado. Se o valor não existe localmente, JavaScript verifica a cadeia de protótipos (usando a propriedade  interna __proto__). Se um objeto na cadeia de protótipos possui um valor para a propriedade, este valor é retornado. Se nenhuma propriedade é encontrada, o Javascript avisa que o objeto não possui a propriedade. Deste modo, o objeto mark possui as seguintes propriedades e valores: 

- -
mark.name = "";
-mark.dept = "general";
-mark.projects = [];
-
- -

The mark object inherits values for the name and dept properties from the prototypical object in mark.__proto__. It is assigned a local value for the projects property by the WorkerBee constructor. This gives you inheritance of properties and their values in JavaScript. Some subtleties of this process are discussed in Property inheritance revisited.

- -

Because these constructors do not let you supply instance-specific values, this information is generic. The property values are the default ones shared by all new objects created from WorkerBee. You can, of course, change the values of any of these properties. So, you could give specific information for mark as follows:

- -
mark.name = "Doe, Mark";
-mark.dept = "admin";
-mark.projects = ["navigator"];
- -

Adding properties

- -

In JavaScript, you can add properties to any object at run time. You are not constrained to use only the properties provided by the constructor function. To add a property that is specific to a single object, you assign a value to the object, as follows:

- -
mark.bonus = 3000;
-
- -

Now, the mark object has a bonus property, but no other WorkerBee has this property.

- -

If you add a new property to an object that is being used as the prototype for a constructor function, you add that property to all objects that inherit properties from the prototype. For example, you can add a specialty property to all employees with the following statement:

- -
Employee.prototype.specialty = "none";
-
- -

As soon as JavaScript executes this statement, the mark object also has the specialty property with the value of "none". The following figure shows the effect of adding this property to the Employee prototype and then overriding it for the Engineer prototype.

- -


- Adding properties

- -

More flexible constructors

- -

The constructor functions shown so far do not let you specify property values when you create an instance. As with Java, you can provide arguments to constructors to initialize property values for instances. The following figure shows one way to do this.

- -


- Specifying properties in a constructor, take 1

- -

The following table shows the Java and JavaScript definitions for these objects.

- -
-

JavaScript

- -

Java

-
- -
-
function Employee (name, dept) {
-  this.name = name || "";
-  this.dept = dept || "general";
-}
-
- -
public class Employee {
-   public String name;
-   public String dept;
-   public Employee () {
-      this("", "general");
-   }
-   public Employee (String name) {
-      this(name, "general");
-   }
-   public Employee (String name, String dept) {
-      this.name = name;
-      this.dept = dept;
-   }
-}
-
-
- -
-
function WorkerBee (projs) {
-
- this.projects = projs || [];
-}
-WorkerBee.prototype = new Employee;
-
- -
public class WorkerBee extends Employee {
-   public String[] projects;
-   public WorkerBee () {
-      this(new String[0]);
-   }
-   public WorkerBee (String[] projs) {
-      projects = projs;
-   }
-}
-
-
- -
-
-function Engineer (mach) {
-   this.dept = "engineering";
-   this.machine = mach || "";
-}
-Engineer.prototype = new WorkerBee;
-
- -
public class Engineer extends WorkerBee {
-   public String machine;
-   public Engineer () {
-      dept = "engineering";
-      machine = "";
-   }
-   public Engineer (String mach) {
-      dept = "engineering";
-      machine = mach;
-   }
-}
-
-
- -

These JavaScript definitions use a special idiom for setting default values:

- -
this.name = name || "";
-
- -

The JavaScript logical OR operator (||) evaluates its first argument. If that argument converts to true, the operator returns it. Otherwise, the operator returns the value of the second argument. Therefore, this line of code tests to see if name has a useful value for the name property. If it does, it sets this.name to that value. Otherwise, it sets this.name to the empty string. This chapter uses this idiom for brevity; however, it can be puzzling at first glance.

- -
-

Note: This may not work as expected if the constructor function is called with arguments which convert to false (like 0 (zero) and empty string (""). In this case the default value will be chosen.

-
- -

With these definitions, when you create an instance of an object, you can specify values for the locally defined properties. You can use the following statement to create a new Engineer:

- -
var jane = new Engineer("belau");
-
- -

Jane's properties are now:

- -
jane.name == "";
-jane.dept == "engineering";
-jane.projects == [];
-jane.machine == "belau"
-
- -

Notice that with these definitions, you cannot specify an initial value for an inherited property such as name. If you want to specify an initial value for inherited properties in JavaScript, you need to add more code to the constructor function.

- -

So far, the constructor function has created a generic object and then specified local properties and values for the new object. You can have the constructor add more properties by directly calling the constructor function for an object higher in the prototype chain. The following figure shows these new definitions.

- -


- Specifying properties in a constructor, take 2

- -

Let's look at one of these definitions in detail. Here's the new definition for the Engineer constructor:

- -
function Engineer (name, projs, mach) {
-  this.base = WorkerBee;
-  this.base(name, "engineering", projs);
-  this.machine = mach || "";
-}
-
- -

Suppose you create a new Engineer object as follows:

- -
var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
-
- -

JavaScript follows these steps:

- -
    -
  1. The new operator creates a generic object and sets its __proto__ property to Engineer.prototype.
  2. -
  3. The new operator passes the new object to the Engineer constructor as the value of the this keyword.
  4. -
  5. The constructor creates a new property called base for that object and assigns the value of the WorkerBee constructor to the base property. This makes the WorkerBee constructor a method of the Engineer object.The name of the base property is not special. You can use any legal property name; base is simply evocative of its purpose.
  6. -
  7. -

    The constructor calls the base method, passing as its arguments two of the arguments passed to the constructor ("Doe, Jane" and ["navigator", "javascript"]) and also the string "engineering". Explicitly using "engineering" in the constructor indicates that all Engineer objects have the same value for the inherited dept property, and this value overrides the value inherited from Employee.

    -
  8. -
  9. Because base is a method of Engineer, within the call to base, JavaScript binds the this keyword to the object created in Step 1. Thus, the WorkerBee function in turn passes the "Doe, Jane" and "engineering" arguments to the Employee constructor function. Upon return from the Employee constructor function, the WorkerBee function uses the remaining argument to set the projects property.
  10. -
  11. Upon return from the base method, the Engineer constructor initializes the object's machine property to "belau".
  12. -
  13. Upon return from the constructor, JavaScript assigns the new object to the jane variable.
  14. -
- -

You might think that, having called the WorkerBee constructor from inside the Engineer constructor, you have set up inheritance appropriately for Engineer objects. This is not the case. Calling the WorkerBee constructor ensures that an Engineer object starts out with the properties specified in all constructor functions that are called. However, if you later add properties to the Employee or WorkerBee prototypes, those properties are not inherited by the Engineer object. For example, assume you have the following statements:

- -
function Engineer (name, projs, mach) {
-  this.base = WorkerBee;
-  this.base(name, "engineering", projs);
-  this.machine = mach || "";
-}
-var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
-Employee.prototype.specialty = "none";
-
- -

The jane object does not inherit the specialty property. You still need to explicitly set up the prototype to ensure dynamic inheritance. Assume instead you have these statements:

- -
function Engineer (name, projs, mach) {
-  this.base = WorkerBee;
-  this.base(name, "engineering", projs);
-  this.machine = mach || "";
-}
-Engineer.prototype = new WorkerBee;
-var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
-Employee.prototype.specialty = "none";
-
- -

Now the value of the jane object's specialty property is "none".

- -

Another way of inheriting is by using the call() / apply() methods. Below are equivalent:

- -
-
function Engineer (name, projs, mach) {
-  this.base = WorkerBee;
-  this.base(name, "engineering", projs);
-  this.machine = mach || "";
-}
-
- -
function Engineer (name, projs, mach) {
-  WorkerBee.call(this, name, "engineering", projs);
-  this.machine = mach || "";
-}
-
-
- -

Using the javascript call() method makes a cleaner implementation because the base is not needed anymore.

- -

Property inheritance revisited

- -

The preceding sections described how JavaScript constructors and prototypes provide hierarchies and inheritance. This section discusses some subtleties that were not necessarily apparent in the earlier discussions.

- -

Local versus inherited values

- -

When you access an object property, JavaScript performs these steps, as described earlier in this chapter:

- -
    -
  1. Check to see if the value exists locally. If it does, return that value.
  2. -
  3. If there is not a local value, check the prototype chain (using the __proto__ property).
  4. -
  5. If an object in the prototype chain has a value for the specified property, return that value.
  6. -
  7. If no such property is found, the object does not have the property.
  8. -
- -

The outcome of these steps depends on how you define things along the way. The original example had these definitions:

- -
function Employee () {
-  this.name = "";
-  this.dept = "general";
-}
-
-function WorkerBee () {
-  this.projects = [];
-}
-WorkerBee.prototype = new Employee;
-
- -

With these definitions, suppose you create amy as an instance of WorkerBee with the following statement:

- -
var amy = new WorkerBee;
-
- -

The amy object has one local property, projects. The values for the name and dept properties are not local to amy and so are gotten from the amy object's __proto__ property. Thus, amy has these property values:

- -
amy.name == "";
-amy.dept == "general";
-amy.projects == [];
-
- -

Now suppose you change the value of the name property in the prototype associated with Employee:

- -
Employee.prototype.name = "Unknown"
-
- -

At first glance, you might expect that new value to propagate down to all the instances of Employee. However, it does not.

- -

When you create any instance of the Employee object, that instance gets a local value for the name property (the empty string). This means that when you set the WorkerBee prototype by creating a new Employee object, WorkerBee.prototype has a local value for the name property. Therefore, when JavaScript looks up the name property of the amy object (an instance of WorkerBee), JavaScript finds the local value for that property in WorkerBee.prototype. It therefore does not look farther up the chain to Employee.prototype.

- -

If you want to change the value of an object property at run time and have the new value be inherited by all descendants of the object, you cannot define the property in the object's constructor function. Instead, you add it to the constructor's associated prototype. For example, assume you change the preceding code to the following:

- -
function Employee () {
-  this.dept = "general";
-}
-Employee.prototype.name = "";
-
-function WorkerBee () {
-  this.projects = [];
-}
-WorkerBee.prototype = new Employee;
-
-var amy = new WorkerBee;
-
-Employee.prototype.name = "Unknown";
-
- -

In this case, the name property of amy becomes "Unknown".

- -

As these examples show, if you want to have default values for object properties and you want to be able to change the default values at run time, you should set the properties in the constructor's prototype, not in the constructor function itself.

- -

Determining instance relationships

- -

Property lookup in JavaScript looks within an object's own properties and, if the property name is not found, it looks within the special object property __proto__. This continues recursively; the process is called "lookup in the prototype chain".

- -

The special property __proto__ is set when an object is constructed; it is set to the value of the constructor's prototype property. So the expression new Foo() creates an object with __proto__ == Foo.prototype. Consequently, changes to the properties of Foo.prototype alters the property lookup for all objects that were created by new Foo().

- -

Every object has a __proto__ object property (except Object); every function has a prototype object property. So objects can be related by 'prototype inheritance' to other objects. You can test for inheritance by comparing an object's __proto__ to a function's prototype object. JavaScript provides a shortcut: the instanceof operator tests an object against a function and returns true if the object inherits from the function prototype. For example,

- -
var f = new Foo();
-var isTrue = (f instanceof Foo);
- -

For a more detailed example, suppose you have the same set of definitions shown in Inheriting properties. Create an Engineer object as follows:

- -
var chris = new Engineer("Pigman, Chris", ["jsd"], "fiji");
-
- -

With this object, the following statements are all true:

- -
chris.__proto__ == Engineer.prototype;
-chris.__proto__.__proto__ == WorkerBee.prototype;
-chris.__proto__.__proto__.__proto__ == Employee.prototype;
-chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype;
-chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
-
- -

Given this, you could write an instanceOf function as follows:

- -
function instanceOf(object, constructor) {
-   object = object.__proto__;
-   while (object != null) {
-      if (object == constructor.prototype)
-         return true;
-      if (typeof object == 'xml') {
-        return constructor.prototype == XML.prototype;
-      }
-      object = object.__proto__;
-   }
-   return false;
-}
-
- -
Note: The implementation above checks the type of the object against "xml" in order to work around a quirk of how XML objects are represented in recent versions of JavaScript. See {{ bug(634150) }} if you want the nitty-gritty details.
- -

Using the instanceOf function defined above, these expressions are true:

- -
instanceOf (chris, Engineer)
-instanceOf (chris, WorkerBee)
-instanceOf (chris, Employee)
-instanceOf (chris, Object)
-
- -

But the following expression is false:

- -
instanceOf (chris, SalesPerson)
-
- -

Global information in constructors

- -

When you create constructors, you need to be careful if you set global information in the constructor. For example, assume that you want a unique ID to be automatically assigned to each new employee. You could use the following definition for Employee:

- -
var idCounter = 1;
-
-function Employee (name, dept) {
-   this.name = name || "";
-   this.dept = dept || "general";
-   this.id = idCounter++;
-}
-
- -

With this definition, when you create a new Employee, the constructor assigns it the next ID in sequence and then increments the global ID counter. So, if your next statement is the following, victoria.id is 1 and harry.id is 2:

- -
var victoria = new Employee("Pigbert, Victoria", "pubs")
-var harry = new Employee("Tschopik, Harry", "sales")
-
- -

At first glance that seems fine. However, idCounter gets incremented every time an Employee object is created, for whatever purpose. If you create the entire Employee hierarchy shown in this chapter, the Employee constructor is called every time you set up a prototype. Suppose you have the following code:

- -
var idCounter = 1;
-
-function Employee (name, dept) {
-   this.name = name || "";
-   this.dept = dept || "general";
-   this.id = idCounter++;
-}
-
-function Manager (name, dept, reports) {...}
-Manager.prototype = new Employee;
-
-function WorkerBee (name, dept, projs) {...}
-WorkerBee.prototype = new Employee;
-
-function Engineer (name, projs, mach) {...}
-Engineer.prototype = new WorkerBee;
-
-function SalesPerson (name, projs, quota) {...}
-SalesPerson.prototype = new WorkerBee;
-
-var mac = new Engineer("Wood, Mac");
-
- -

Further assume that the definitions omitted here have the base property and call the constructor above them in the prototype chain. In this case, by the time the mac object is created, mac.id is 5.

- -

Depending on the application, it may or may not matter that the counter has been incremented these extra times. If you care about the exact value of this counter, one possible solution involves instead using the following constructor:

- -
function Employee (name, dept) {
-   this.name = name || "";
-   this.dept = dept || "general";
-   if (name)
-      this.id = idCounter++;
-}
-
- -

When you create an instance of Employee to use as a prototype, you do not supply arguments to the constructor. Using this definition of the constructor, when you do not supply arguments, the constructor does not assign a value to the id and does not update the counter. Therefore, for an Employee to get an assigned id, you must specify a name for the employee. In this example, mac.id would be 1.

- -

No multiple inheritance

- -

Some object-oriented languages allow multiple inheritance. That is, an object can inherit the properties and values from unrelated parent objects. JavaScript does not support multiple inheritance.

- -

Inheritance of property values occurs at run time by JavaScript searching the prototype chain of an object to find a value. Because an object has a single associated prototype, JavaScript cannot dynamically inherit from more than one prototype chain.

- -

In JavaScript, you can have a constructor function call more than one other constructor function within it. This gives the illusion of multiple inheritance. For example, consider the following statements:

- -
function Hobbyist (hobby) {
-   this.hobby = hobby || "scuba";
-}
-
-function Engineer (name, projs, mach, hobby) {
-   this.base1 = WorkerBee;
-   this.base1(name, "engineering", projs);
-   this.base2 = Hobbyist;
-   this.base2(hobby);
-   this.machine = mach || "";
-}
-Engineer.prototype = new WorkerBee;
-
-var dennis = new Engineer("Doe, Dennis", ["collabra"], "hugo")
-
- -

Further assume that the definition of WorkerBee is as used earlier in this chapter. In this case, the dennis object has these properties:

- -
dennis.name == "Doe, Dennis"
-dennis.dept == "engineering"
-dennis.projects == ["collabra"]
-dennis.machine == "hugo"
-dennis.hobby == "scuba"
-
- -

So dennis does get the hobby property from the Hobbyist constructor. However, assume you then add a property to the Hobbyist constructor's prototype:

- -
Hobbyist.prototype.equipment = ["mask", "fins", "regulator", "bcd"]
-
- -

The dennis object does not inherit this new property.

- -
{{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}
diff --git a/files/pt-br/web/javascript/guide/formatando_texto/index.html b/files/pt-br/web/javascript/guide/formatando_texto/index.html deleted file mode 100644 index 1b4bb50772..0000000000 --- a/files/pt-br/web/javascript/guide/formatando_texto/index.html +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Formatando texto -slug: Web/JavaScript/Guide/Formatando_texto -tags: - - Guía - - JavaScript -translation_of: Web/JavaScript/Guide/Text_formatting ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
- -

Esse capítulo introduz como trabalhar com strings e texto em JavaScript.

- -

Strings

- -

O tipo {{Glossary("String")}} do JavaScript é usado para representar informações de texto. É um conjunto de "elementos" composto por valores inteiros de 16-bits sem sinal. Cada elemento dentro da String ocupa uma posição dentro dessa String. O primeiro elemento está no índice 0, o próximo no índice 1, e assim sucessivamente. O tamanho de uma String é a quantidade de elementos que ela possui. Você pode criar strings usando strings literais ou objetos string.

- -

Strings literais

- -

Você pode criar strings usando aspas simples ou aspas duplas:

- -
'foo'
-"bar"
- -

Strings mais avançadas podem ser criadas usando sequências de escape:

- -

Sequências de escape hexadecimais

- -

O número depois de \x é interpretado como um número hexadecimal.

- -
'\xA9' // "©"
-
- -

Sequências de escape unicode

- -

As sequências de escape unicode requerem no mínimo quatro caracteres depois do \u.

- -
'\u00A9' // "©"
- -

Sequências de escape Unicode code point

- -

É novo no ECMAScript 6. Com essas sequências, cada caractere pode ser "escapado" usando números hexadecimais, sendo possível usar pontos de código Unicode de até 0x10FFFF. Com escapes Unicode simples muitas vezes é necessário escrever as metades substitutas separadamente para obter o mesmo resultado.

- -

Veja também {{jsxref("String.fromCodePoint()")}} or {{jsxref("String.prototype.codePointAt()")}}.

- -
'\u{2F804}'
-
-// o mesmo com escapes Unicode simples
-'\uD87E\uDC04'
- -

Objetos String

- -

O objeto {{jsxref("String")}} é como uma "capa" ao redor do tipo primitivo string.

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

Você pode chamar qualquer um dos métodos do objeto String em cima de uma string literal — JavaScript automaticamente converte a string literal em um objeto String temporário, chama o método, e então descarta o objeto String temporário. Você pode também usar a propriedade String.length com uma string literal.

- -

Você deve usar strings literais a menos que você realmente precise usar um objeto String, pois objetos String podem ter comportamentos inesperados. Por exemplo:

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

Um objeto String possui uma propriedade, length, que indica o número de caracteres na string. Por exemplo, o código a seguir atribui o valor 11 à variável x, pois "Olá, mundo!" possui 11 caracteres:

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

Um objeto String possui uma variedade de métodos: por exemplo aqueles que retornam uma variação da própria string, como substring e toUpperCase.

- -

A tabela a seguir lista os métodos de objetos {{jsxref("String")}}.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Métodos de String

-
MétodoDescrição
{{jsxref("String.charAt", "charAt")}}, {{jsxref("String.charCodeAt", "charCodeAt")}}, {{jsxref("String.codePointAt", "codePointAt")}}Retorna o código do caractere ou o caractere em uma posição específica na string.
{{jsxref("String.indexOf", "indexOf")}}, {{jsxref("String.lastIndexOf", "lastIndexOf")}}Retorna a posição de uma substring específica na string ou a última posição da substring específica, respectivamente.
{{jsxref("String.startsWith", "startsWith")}}, {{jsxref("String.endsWith", "endsWith")}}, {{jsxref("String.includes", "includes")}}Retorna se uma string começa, termina ou contém uma outra string específica.
{{jsxref("String.concat", "concat")}}Concatena o texto de duas strings e retorna uma nova string.
{{jsxref("String.fromCharCode", "fromCharCode")}}, {{jsxref("String.fromCodePoint", "fromCodePoint")}}Cria uma string a partir de uma sequência específica de valores Unicode. Esse é um método da classe String, não de uma instância do tipo String.
{{jsxref("String.split", "split")}}Separa um objeto String em um array de strings, separando a string em substrings.
{{jsxref("String.slice", "slice")}}Extrai uma seção de uma string e retorna uma nova string.
{{jsxref("String.substring", "substring")}}, {{jsxref("String.substr", "substr")}}Retorna um subconjunto específico de uma string, definindo os índices inicial e final, ou definindo um índice e um tamanho.
{{jsxref("String.match", "match")}}, {{jsxref("String.replace", "replace")}}, {{jsxref("String.search", "search")}}Trabalha com expressões regulares.
{{jsxref("String.toLowerCase", "toLowerCase")}}, {{jsxref("String.toUpperCase", "toUpperCase")}} -

Retorna a string com todos caracteres em minúsculo, ou maiúsculo, respectivamente.

-
{{jsxref("String.normalize", "normalize")}}Retorna a Forma Normalizada Unicode (Unicode Normalization Form) da string que chama o método.
{{jsxref("String.repeat", "repeat")}}Retorna uma string contendo os elementos do objeto repetidos pela quantidade de vezes dada.
{{jsxref("String.trim", "trim")}}Retira espaços em branco no começo e no final da string.
- -

Template strings com várias linhas

- -

Template strings são strings literais que permitem expressões no seu conteúdo. Você pode usar os recursos de strings com multiplas linhas e interpolações de string com as template strings.

- -

Template strings são declaradas com o acento grave (``) ao invés de aspas simples ou aspas duplas. Essas strings podem conter place holders. Os place holders são indicados pelo cifrão e com chaves ( ${expressao} ).

- -

Várias linhas (Multi-lines)

- -

Qualquer caractere de nova linha ( '\n' ) inserido na string também faz parte das template string. Usando strings normais, você teria que usar a sintaxe a seguir para conseguir uma string de várias linhas

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

Para obter o mesmo efeito com strings multi-lines, você pode agora escrever:

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

Expressões inseridas

- -

Para conseguir inserir expressões com strings normais, você teria que usar a seguinte sintaxe:

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

Agora, com template strings, você tem a capacidade de usar uma forma mais simples e legível para fazer essas substituições:

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

Para mais informações, leia sobre Template strings na referência JavaScript.

- -

Internacionalização

- -

O objeto {{jsxref("Intl")}} é o namespace para a API de Internacionalização do ECMAScript, que oferece comparação de strings sensíveis à linguagem, formatação de números, e formatação de datas e horas. Os construtores para os objetos {{jsxref("Collator")}}, {{jsxref("NumberFormat")}}, e {{jsxref("DateTimeFormat")}} são propriedades do objeto Intl.

- -

Formatação de data e hora

- -

O objeto {{jsxref("DateTimeFormat")}} é útil para a formatação de data e hora. O código a seguir formata uma data em inglês no formato que é utilizado nos Estados Unidos. (O resultado é diferente em outro fuso horário).

- -
var msPorDia = 24 * 60 * 60 * 1000; // número de milisegundos em um dia
-
-// July 17, 2014 00:00:00 UTC.
-var july172014 = new Date(msPorDia * (44 * 365 + 11 + 197));
-
-var opcoes = { year: "2-digit", month: "2-digit", day: "2-digit",
-                hour: "2-digit", minute: "2-digit", timeZoneName: "short" };
-var americanDateTime = new Intl.DateTimeFormat("en-US", opcoes).format;
-
-console.log(americanDateTime(july172014)); // 07/16/14, 5:00 PM PDT
-
- -

Formatação de números

- -

O objeto {{jsxref("NumberFormat")}} é útil para formatar números, por exemplo unidade monetária.

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

Collation

- -

O objeto {{jsxref("Collator")}} é usado para comparar e ordenar strings.

- -

Por exemplo, existem atualmente duas ordens diferentes de classificação no Alemão: listaTelefônica e dicionário. A ordenação da listaTelefônica enfatiza o som, e é como se "ä", "ö", e assim por diante, fossem expandidos para "ae", "oe", e assim sucessivamente, para definir a ordem.

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

Algumas palavras do alemão são conjugadas com tremas extras, mas no dicionário essas palavras são ordenadas ignorando os tremas (exceto quando ordenando palavras que tem apenas o trema como diferença: schon antes de schön).

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

Para mais informação sobre a API {{jsxref("Intl")}}, veja também Introducing the JavaScript Internationalization API (em inglês).

- -
{{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
diff --git a/files/pt-br/web/javascript/guide/functions/index.html b/files/pt-br/web/javascript/guide/functions/index.html new file mode 100644 index 0000000000..7077d1787b --- /dev/null +++ b/files/pt-br/web/javascript/guide/functions/index.html @@ -0,0 +1,640 @@ +--- +title: Funções +slug: Web/JavaScript/Guide/Funções +tags: + - Funções JavaScript + - Guia(2) + - Iniciante + - JavaScript +translation_of: Web/JavaScript/Guide/Functions +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}
+ +

Funções são blocos de construção fundamentais em JavaScript. Uma função é um procedimento de JavaScript - um conjunto de instruções que executa uma tarefa ou calcula um valor. Para usar uma função, você deve defini-la em algum lugar no escopo do qual você quiser chamá-la.

+ +

Veja também o capítulo de referência sobre funções JavaScript para conhecer os detalhes.

+ +

Definindo Funções

+ +

Declarando uma função

+ +

A definição da função (também chamada de declaração de função) consiste no uso da palavra chave function, seguida por:

+ + + +

Por exemplo, o código a seguir define uma função simples chamada square:

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

A função square recebe um argumento chamado numero. A função consiste em uma instrução que indica para retornar o argumento da função (isto é, numero) multiplicado por si mesmo. A declaração return especifica o valor retornado pela função.

+ +
return numero * numero;
+
+ +

Parâmetros primitivos (como um número) são passados para as funções por valor; o valor é passado para a função, mas se a função altera o valor do parâmetro, esta mudança não reflete globalmente ou na função chamada.

+ +

Se você passar um objeto (ou seja, um  valor não primitivo, tal como {{jsxref("Array")}} ou um objeto definido por você) como um parâmetro e a função alterar as propriedades do objeto, essa mudança é visível fora da função, conforme mostrado no exemplo a seguir:

+ +
function minhaFuncao(objeto) {
+  objeto.make = "Toyota";
+}
+
+var meucarro = {make: "Honda", model: "Accord", year: 1998};
+var x, y;
+
+x = meucarro.make;     // x recebe o valor "Honda"
+
+minhaFuncao(meucarro);
+y = meucarro.make;     // y recebe o valor "Toyota"
+                    // (a propriedade make foi alterada pela função)
+
+ +

Expressão de função

+ +

Embora a declaração de função acima seja sintaticamente uma declaração, funções também podem ser criadas por uma expressão de função. Tal função pode ser anônima; ele não tem que ter um nome. Por exemplo, a função square poderia ter sido definida como:

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

No entanto, um nome pode ser fornecido com uma expressão de função e pode ser utilizado no interior da função para se referir a si mesma, ou em um debugger para identificar a função em stack traces:

+ +
var fatorial = function fac(n) {return n<2 ? 1 : n*fac(n-1)};
+
+console.log(fatorial(3));
+
+ +

As expressões de função são convenientes ao passar uma função como um argumento para outra função. O exemplo a seguir mostra uma função map sendo definida e, em seguida, chamada com uma função anônima como seu primeiro parâmetro:

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

O código a seguir:

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

retorna [0, 1, 8, 125, 1000].

+ +

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

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

Além de definir funções, você também pode usar o construtor {{jsxref("Function")}} para criar funções a partir de uma string em tempo real, como no método {{jsxref("eval()")}}.

+ +

Um método é uma função invocada por um objeto. Leia mais sobre objetos e métodos em Trabalhando com Objetos.

+ +

Chamando funções

+ +

A definição de uma função não a executa. Definir a função é simplesmente nomear a função e especificar o que fazer quando a função é chamada. Chamar a função executa realmente as ações especificadas com os parâmetros indicados. Por exemplo, se você definir a função square, você pode chamá-la do seguinte modo: 

+ +
square(5);
+
+ +

A declaração anterior chama a função com o argumento 5. A função executa as instruções e retorna o valor 25.

+ +

Funções devem estar no escopo quando são chamadas, mas a declaração de uma função pode ser puxada para o topo (aparecem abaixo da chamada no código), como neste exemplo:

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

O escopo de uma função é a função na qual ela é declarada, ou todo o programa se ela é declarada no nível superior.

+ +
+

Nota: Isso funciona apenas quando a definição da função usa a sintaxe acima (ex., function funcNome(){ }). O código a seguir não vai funcionar.

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

Os argumentos de uma função não estão limitados a strings e números. Você pode passar objetos para uma função. A função show_props (definido em Trabalhando com Objetos) é um exemplo de uma função que recebe um objeto como um argumento.

+ +

Um função pode chamar a si mesma. Por exemplo, a função que calcula os fatoriais recursivamente:

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

Você poderia, então, calcular os fatoriais de um a cinco:

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

Há outras maneiras de chamar funções. Muitas vezes há casos em que uma função precisa ser chamada dinamicamente, ou o número de argumentos de uma função varia, ou em que o contexto da chamada de função precisa ser definido para um objeto específico determinado em tempo de execução. Acontece que as funções são, por si mesmas, objetos, e esses objetos por sua vez têm métodos (veja objeto {{jsxref("Function")}}). Um desses, o método {{jsxref("Function.apply", "apply()")}}, pode ser usado para atingir esse objetivo.

+ +

Escopo da função

+ +

As variáveis definidas no interior de uma função não podem ser acessadas de nenhum lugar fora da função, porque a variável está definida apenas no escopo da função. No entanto, uma função pode acessar todas variáveis e funções definida fora do escopo onde ela está definida. Em outras palavras, a função definida no escopo global pode acessar todas as variáveis definidas no escopo global. A função definida dentro de outra função também pode acessar todas as variáveis definidas na função hospedeira e outras variáveis ao qual a função hospedeira tem acesso.

+ +
// As seguintes variáveis são definidas no escopo global
+var num1 = 20,
+    num2 = 3,
+    nome = "Chamahk";
+
+// Esta função é definida no escopo global
+function multiplica() {
+  return num1 * num2;
+}
+
+multiplica(); // Retorna 60
+
+// Um exemplo de função aninhada
+function getScore () {
+  var num1 = 2,
+      num2 = 3;
+
+  function add() {
+    return nome + " scored " + (num1 + num2);
+  }
+
+  return add();
+}
+
+getScore(); // Retorna "Chamahk scored 5"
+
+ +

Escopo e a pilha de função

+ +

Recursão

+ +

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

+ +
    +
  1. o nome da função
  2. +
  3. arguments.callee
  4. +
  5. uma variável no escopo que se refere a função
  6. +
+ +

Por exemplo, considere a seguinte definição de função:

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

Dentro do corpo da função, todos, a seguir, são equivalentes:

+ +
    +
  1. bar()
  2. +
  3. arguments.callee()
  4. +
  5. foo()
  6. +
+ +

Uma função que chama a si mesma é chamada de função recursiva. Em alguns casos, a recursividade é análoga a um laço. Ambos executam o código várias vezes, e ambos necessitam de uma condição (para evitar um laço infinito, ou melhor, recursão infinita, neste caso). Por exemplo,  o seguinte laço:

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

pode ser convertido em função recursiva e uma chamada para a função:

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

No entanto, alguns algoritmos não podem ser simples laços iterativos. Por exemplo, conseguir todos os nós da estrutura de uma árvore (por exemplo, o DOM) é mais fácil se feito recursivamente:

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

Em comparação ao laço da função, cada chamada recursiva realiza outras chamadas recursivas.

+ +

É possível converter qualquer algoritmo recursivo para um não recursivo, mas muitas vezes a lógica é muito mais complexa e exige o uso de pilhas. Na verdade a própria recursão usa pilha: a pilha de função.

+ +

O comportamento da pilha pode ser vista a seguir no exemplo:

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

que produz:

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

Funções aninhadas e closures

+ +

Você pode aninhar uma função dentro de outra. A função aninhada (interna) é acessível apenas para a função que a contém (exterior). Isso constitui também uma closure. Uma closure é uma expressão (tipicamente uma função) que pode ter variáveis livres em conjunto com um ambiente que conecta estas variáveis (que "fecha" a expressão).

+ +

Uma vez que uma função aninhada é uma closure, isto significa que uma função aninhada pode "herdar" os argumentos e variáveis de sua função de contenção. Em outras palavras, a função interior contém o escopo da função exterior.

+ +

Em resumo:

+ + + +

O exemplo a seguir mostra as funções aninhadas:

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

Uma vez que a função interna forma uma closure, você pode chamar a função externa e especificar argumentos para a função externa e interna:

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

Preservação  de variáveis

+ +

Observe como x é preservado quando dentro é retornado. Uma closure deve preservar os argumentos e variáveis em todos os escopos que ela referencia. Uma vez que cada chamada fornece potencialmente argumentos diferentes, uma nova closure é criada para cada chamada de fora. A memória só poderá ser liberada quando o dentro retornado já não é mais acessível.

+ +

Isso não é diferente de armazenar referências em outros objetos, mas muitas vezes é menos óbvio, porque um não define diretamente as referências e não pode inspecioná-las.

+ +

Múltiplas funções aninhadas

+ +

Funções podem ter múltiplo aninhamento, por exemplo, a função (A) contém a função (B) que contém a função (C). Tanto as funções B e C formam uma closure, então B pode acessar A, e C pode acessar B. Além disso, uma vez que C pode acessar B que pode acessar A, C também pode acessar A. Assim, a closure pode conter vários escopos; eles recursivamente contém o escopo das funções que os contém. Isso é chamado encadeamento de escopo. (O motivo de ser chamado "encadeamento" será explicado mais tarde).

+ +

Considere o seguinte exemplo:

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

Neste exemplo, C acessa y do B e x do A. Isso pode ser feito porque:

+ +
    +
  1. B forma uma closure incluindo A, isto é, B pode acessar argumentos e variáveis de A.
  2. +
  3. C forma uma closure incluindo B.
  4. +
  5.  Devido a closure B inclui A, a closure C inclui A, C pode acessar tanto argumentos e variáveis de B como de A. Em outras palavras, C encadeia o escopo de B e A, nesta ordem.
  6. +
+ +

O inverso, no entanto, não é verdadeiro. A não pode acessar C, porque A não pode acessar qualquer argumento ou variável de B. Assim, C é privado somente a B.

+ +

Conflitos de nome

+ +

Quando dois argumentos ou variáveis nos escopos da closure tem o mesmo nome, há um conflito de nome. Mas escopos internos tem prioridade, por isso o escopo mais interno tem a maior prioridade, enquanto que o escopo mais externo tem a menor. Esta é a cadeia de escopo. O primeiro da cadeia é o escopo mais interno, e o último é o escopo mais externo. Considere o seguinte:

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

O  conflito de nome acontece na declaração return x e está entre o parâmetro x de dentro e a variável x de fora. A cadeia de escopo aqui é {dentro, fora, objeto global}. Por isso o x de dentro tem precedência sobre o x de fora, e 20 (x de dentro) é retornado em vez de 10 (x de fora).

+ +

Closures

+ +

Closures são um dos recursos mais poderosos de JavaScript. JavaScript permite o aninhamento de funções e garante acesso completo à função interna a todas as variáveis e funções definidas dentro da função externa (e todas as outras variáveis e funções que a função externa tem acesso). No entanto, a função externa não tem acesso às variáveis e funções definidas dentro da função interna. Isto proporciona uma espécie de segurança para as variáveis da função interna. Além disso, uma vez  que a função interna tem acesso ao escopo da função externa, as variáveis e funções definidas na função externa vão durar na memória mais do que a própria função externa, isto se a função interna permanecer na memória mais tempo do que a função externa. Uma closure é criada quando a função interna é de alguma forma disponibilizada para qualquer escopo fora da função externa.

+ +
var pet = function(nome) {          // A função externa define uma variável "nome"
+      var getNome = function() {
+        return nome;                // A função interna tem acesso à variável "nome"  da função externa
+      }
+
+      return getNome;               // Retorna a função interna, expondo-a assim para escopos externos
+    },
+    myPet = pet("Vivie");
+
+myPet();                            // Retorna "Vivie"
+
+ +

Ela pode ser  mais complexa que o código acima. Um objeto contendo métodos para manipular as variáveis da função externa pode ser devolvida.

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

Nos códigos acima, a variável nome da função externa é acessível para as funções internas, e não há nenhuma outra maneira para acessar as variáveis internas, exceto pelas funções internas. As variáveis internas da função interna atuam como armazenamento seguro para as funções internas. Elas armazenam "persistentes", mas seguros, os dados com os quais as funções internas irão trabalhar. As funções não tem  que ser atribuídas a uma variável, ou ter um nome.

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

Há, no entanto, uma série de armadilhas que se deve ter cuidado ao usar closures. Se uma função fechada define uma variável com o mesmo nome de uma variável em um escopo externo, não há nenhuma maneira de se referir para a variável em um escopo externo novamente.

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

A palavra reservada this é muito complicada em closures, elas têm de ser usadas com muito cuidado. O objeto ao que this se refere depende completamente de onde a função foi chamada, ao invés de onde ela foi definida.

+ +

Usando objeto de argumentos

+ +

Os argumentos de uma função são mantidos em um objeto do tipo array. Dentro de uma função, você pode endereçar os argumentos passados para ele conforme: 

+ +
arguments[i]
+
+ +

onde i é um número ordinal do argumento, começando com zero. Então, o primeiro argumento passado para a função seria arguments[0]. O número total de argumentos é indicado por arguments.length.

+ +

Usando o objeto arguments, você pode chamar a função com mais argumentos do que o formalmente declarado. Isso muitas vezes é útil se você não sabe de antemão quantos argumentos serão passados para a função. Você pode usar arguments.length para determinar a quantidade de argumentos passados para a função, e então acessar cada argumento usando o objeto arguments.

+ +

Por exemplo, considere uma função que concatena várias strings. O argumento formal para a função é uma string que especifica os caracteres que separam os itens para concatenar.  A função definida como segue:

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

Você pode passar qualquer quantidade de argumentos para esta função, e ela concatena cada argumento na string "list":

+ +
// retorna "red, orange, blue, "
+myConcat(", ", "red", "orange", "blue");
+
+// retorna "elephant; giraffe; lion; cheetah; "
+myConcat("; ", "elephant", "giraffe", "lion", "cheetah");
+
+// retorna "sage. basil. oregano. pepper. parsley. "
+myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
+
+ +
+

Nota: A variável arguments é "como um array", mas não é um array. Ela é como um array pois possui um índice numerado e a propriedade length. No entanto, não possui todos os métodos de manipulação de array. 

+
+ +

Veja objeto {{jsxref("Function")}} na referência do JavaScript para maiores informações.

+ +

Parâmetros de função

+ +

Começando com ECMAScript 6, há dois tipos novos de parâmetros: parâmetros padrão e parâmetros rest.

+ +

Parâmetros padrão

+ +

Em JavaScript, parâmetros padrões de funções são undefined. No entanto, em algumas situações pode ser útil definir um valor padrão diferente. Isto é onde os parâmetros padrão podem ajudar.

+ +

No passado, a estratégia geral para definir padrões era testar os valores de parâmetro no corpo da função e atribuir um valor se eles fossem undefined. Se, no exemplo a seguir, nenhum valor é fornecido para b na chamada, seu valor seria undefined ao avaliar a*b e a chamada para multiplicar retornaria NaN. No entanto, isso é pego com a segunda linha neste exemplo:

+ +
function multiplicar(a, b) {
+  b = typeof b !== 'undefined' ?  b : 1;
+
+  return a*b;
+}
+
+multiplicar(5); // 5
+ +

Com parâmetros padrão, a verificação no corpo da função não é mais necessária. Agora você pode simplesmente colocar 1 como valor padrão para b no campo de declaração de parâmetros:

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

Mais detalhes, consulte parâmetros padrão na referência.

+ +

Parâmetros rest

+ +

A sintaxe de parâmetro rest permite representar um número indefinido de argumentos como um array. No exemplo, usamos parâmetros rest para coletar argumentos do segundo argumento ao último. Então os multiplicamos pelo primeiro argumento. Neste exemplo é usado uma arrow function, que será introduzida na próxima seção.

+ +
function multiplicar(multiplicador, ...args) {
+  return args.map(x => multiplicador * x);
+}
+
+var arr = multiplicar(2, 1, 2, 3);
+console.log(arr); // [2, 4, 6]
+ +

Funções de seta

+ +

Uma expressão função de seta (anteriormente conhecida como função de seta gorda) tem uma sintaxe pequena em comparação com a expressão de função e lexicalmente vincula o valor this. Funções de seta são sempre anônimas. Consulte também no blog hacks.mozilla.org no post: "ES6 In Depth: Arrow functions".

+ +

Dois fatores influenciaram a introdução de funções de seta: funções mais curtas e o léxico this.

+ +

Funções curtas

+ +

Em alguns padrões funcionais, funções curtas são bem-vindas. Compare:

+ +
var a = [
+  "Hydrogen",
+  "Helium",
+  "Lithium",
+  "Beryl­lium"
+];
+
+var a2 = a.map(function(s){ return s.length });
+
+var a3 = a.map( s => s.length );
+ +

Léxico this

+ +

Até as funções de seta, cada nova função definia seu próprio valor this (um novo objeto no caso de um construtor, indefinido em chamadas de função no modo estrito, o objeto de contexto se a função é chamada como um "método de objeto", etc.). Isso pode ser irritante com um estilo de programação orientada a objetos.

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

No ECMAScript 3/5, este problema foi resolvido atribuindo o valor em this a uma variável que poderia ser fechada.

+ +
function Pessoa() {
+  var self = this; // Alguns preferem 'that' em vez de 'self'. 
+                   // Escolha um e seja consistente.
+  self.idade = 0;
+
+  setInterval(function crescer() {
+    // A chamada de retorno refere-se à variável 'self' na qual
+    // o valor é o objeto esperado.
+    self.idade++;
+  }, 1000);
+}
+ +

Como alternativa, uma função vinculada poderia ser criada para que o valor da propriedade this seja passado para a função crescer().

+ +

Funções de seta capturam o valor this do contexto delimitado, então o código a seguir funciona conforme o esperado.

+ +
function Pessoa(){
+  this.idade = 0;
+
+  setInterval(() => {
+    this.idade++; // propriedade |this|refere ao objeto pessoa
+  }, 1000);
+}
+
+var p = new Pessoa();
+ +

Funções pré-definidas

+ +

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

+ +
+
{{jsxref("Global_Objects/eval", "eval()")}}
+
+

O método eval() avalia código JavaScript representado como uma string.

+
+
{{jsxref("Global_Objects/uneval", "uneval()")}} {{non-standard_inline}}
+
+

O método uneval() cria uma representação de string do código-fonte de um  {{jsxref("Object")}}.

+
+
{{jsxref("Global_Objects/isFinite", "isFinite()")}}
+
+

A função global isFinite() determina se o valor passado é um número finito. Se necessário, o parâmetro é primeiro convertido para um número.

+
+
{{jsxref("Global_Objects/isNaN", "isNaN()")}}
+
+

A função isNaN() determina se um valor é {{jsxref("Global_Objects/NaN", "NaN")}} ou não. Nota: coerção dentro da função isNaN tem regras interessantes; você pode, alternativamente, querer usar {{jsxref("Number.isNaN()")}}, como definido no ECMAScript 6,  ou você pode usar typeof para determinar se o valor não é um número.

+
+
{{jsxref("Global_Objects/parseFloat", "parseFloat()")}}
+
+

A função parseFloat() analisa um argumento do tipo string e retorna um número de ponto flutuante.

+
+
{{jsxref("Global_Objects/parseInt", "parseInt()")}}
+
+

A função parseInt() analisa um argumento do tipo string e retorna um inteiro da base especificada (base do sistema numérico).

+
+
{{jsxref("Global_Objects/decodeURI", "decodeURI()")}}
+
+

A função decodeURI() decodifica uma Uniform Resource Identifier (URI) criada anteriormente por {{jsxref("Global_Objects/encodeURI", "encodeURI")}} ou por uma rotina similar.

+
+
{{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent()")}}
+
+

O método decodeURIComponent() decodifica um componente Uniform Resource Identifier (URI) criado anteriormente por {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} ou por uma rotina similar.

+
+
{{jsxref("Global_Objects/encodeURI", "encodeURI()")}}
+
+

O método encodeURI() codifica um Uniform Resource Identifier (URI), substituindo cada ocorrência de determinados caracteres por um, dois, três, ou quatro sequências de escape que representa a codificação UTF-8 do caractere (só serão quatro sequências de escape para caracteres compostos de dois caracteres "substitutos").

+
+
{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}}
+
+

O método encodeURIComponent() codifica um componente Uniform Resource Identifier (URI), substituindo cada ocorrência de determinados caracteres por um, dois, três, ou quatro sequências de escape que representa a codificação UTF-8 do caractere (só serão quatro sequências de escape para caracteres compostos de dois caracteres "substitutos").

+
+
{{jsxref("Global_Objects/escape", "escape()")}} {{deprecated_inline}}
+
+

O método obsoleto escape() calcula uma nova string na qual certos caracteres foram substituídos por uma sequência de escape hexadecimal. Use {{jsxref("Global_Objects/encodeURI", "encodeURI")}} ou {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} em vez disso.

+
+
{{jsxref("Global_Objects/unescape", "unescape()")}} {{deprecated_inline}}
+
+

O método obsoleto unescape() calcula uma nova string na qual sequências de escape hexadecimais são substituídas pelo caractere que ela representa. As sequências de escape podem ser introduzidas por uma função como {{jsxref("Global_Objects/escape", "escape")}}. Por unescape() estar obsoleto, use {{jsxref("Global_Objects/decodeURI", "decodeURI()")}} ou {{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent")}} ao invés dele.

+
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}

diff --git "a/files/pt-br/web/javascript/guide/fun\303\247\303\265es/index.html" "b/files/pt-br/web/javascript/guide/fun\303\247\303\265es/index.html" deleted file mode 100644 index 7077d1787b..0000000000 --- "a/files/pt-br/web/javascript/guide/fun\303\247\303\265es/index.html" +++ /dev/null @@ -1,640 +0,0 @@ ---- -title: Funções -slug: Web/JavaScript/Guide/Funções -tags: - - Funções JavaScript - - Guia(2) - - Iniciante - - JavaScript -translation_of: Web/JavaScript/Guide/Functions ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}
- -

Funções são blocos de construção fundamentais em JavaScript. Uma função é um procedimento de JavaScript - um conjunto de instruções que executa uma tarefa ou calcula um valor. Para usar uma função, você deve defini-la em algum lugar no escopo do qual você quiser chamá-la.

- -

Veja também o capítulo de referência sobre funções JavaScript para conhecer os detalhes.

- -

Definindo Funções

- -

Declarando uma função

- -

A definição da função (também chamada de declaração de função) consiste no uso da palavra chave function, seguida por:

- - - -

Por exemplo, o código a seguir define uma função simples chamada square:

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

A função square recebe um argumento chamado numero. A função consiste em uma instrução que indica para retornar o argumento da função (isto é, numero) multiplicado por si mesmo. A declaração return especifica o valor retornado pela função.

- -
return numero * numero;
-
- -

Parâmetros primitivos (como um número) são passados para as funções por valor; o valor é passado para a função, mas se a função altera o valor do parâmetro, esta mudança não reflete globalmente ou na função chamada.

- -

Se você passar um objeto (ou seja, um  valor não primitivo, tal como {{jsxref("Array")}} ou um objeto definido por você) como um parâmetro e a função alterar as propriedades do objeto, essa mudança é visível fora da função, conforme mostrado no exemplo a seguir:

- -
function minhaFuncao(objeto) {
-  objeto.make = "Toyota";
-}
-
-var meucarro = {make: "Honda", model: "Accord", year: 1998};
-var x, y;
-
-x = meucarro.make;     // x recebe o valor "Honda"
-
-minhaFuncao(meucarro);
-y = meucarro.make;     // y recebe o valor "Toyota"
-                    // (a propriedade make foi alterada pela função)
-
- -

Expressão de função

- -

Embora a declaração de função acima seja sintaticamente uma declaração, funções também podem ser criadas por uma expressão de função. Tal função pode ser anônima; ele não tem que ter um nome. Por exemplo, a função square poderia ter sido definida como:

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

No entanto, um nome pode ser fornecido com uma expressão de função e pode ser utilizado no interior da função para se referir a si mesma, ou em um debugger para identificar a função em stack traces:

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

As expressões de função são convenientes ao passar uma função como um argumento para outra função. O exemplo a seguir mostra uma função map sendo definida e, em seguida, chamada com uma função anônima como seu primeiro parâmetro:

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

O código a seguir:

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

retorna [0, 1, 8, 125, 1000].

- -

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

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

Além de definir funções, você também pode usar o construtor {{jsxref("Function")}} para criar funções a partir de uma string em tempo real, como no método {{jsxref("eval()")}}.

- -

Um método é uma função invocada por um objeto. Leia mais sobre objetos e métodos em Trabalhando com Objetos.

- -

Chamando funções

- -

A definição de uma função não a executa. Definir a função é simplesmente nomear a função e especificar o que fazer quando a função é chamada. Chamar a função executa realmente as ações especificadas com os parâmetros indicados. Por exemplo, se você definir a função square, você pode chamá-la do seguinte modo: 

- -
square(5);
-
- -

A declaração anterior chama a função com o argumento 5. A função executa as instruções e retorna o valor 25.

- -

Funções devem estar no escopo quando são chamadas, mas a declaração de uma função pode ser puxada para o topo (aparecem abaixo da chamada no código), como neste exemplo:

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

O escopo de uma função é a função na qual ela é declarada, ou todo o programa se ela é declarada no nível superior.

- -
-

Nota: Isso funciona apenas quando a definição da função usa a sintaxe acima (ex., function funcNome(){ }). O código a seguir não vai funcionar.

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

Os argumentos de uma função não estão limitados a strings e números. Você pode passar objetos para uma função. A função show_props (definido em Trabalhando com Objetos) é um exemplo de uma função que recebe um objeto como um argumento.

- -

Um função pode chamar a si mesma. Por exemplo, a função que calcula os fatoriais recursivamente:

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

Você poderia, então, calcular os fatoriais de um a cinco:

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

Há outras maneiras de chamar funções. Muitas vezes há casos em que uma função precisa ser chamada dinamicamente, ou o número de argumentos de uma função varia, ou em que o contexto da chamada de função precisa ser definido para um objeto específico determinado em tempo de execução. Acontece que as funções são, por si mesmas, objetos, e esses objetos por sua vez têm métodos (veja objeto {{jsxref("Function")}}). Um desses, o método {{jsxref("Function.apply", "apply()")}}, pode ser usado para atingir esse objetivo.

- -

Escopo da função

- -

As variáveis definidas no interior de uma função não podem ser acessadas de nenhum lugar fora da função, porque a variável está definida apenas no escopo da função. No entanto, uma função pode acessar todas variáveis e funções definida fora do escopo onde ela está definida. Em outras palavras, a função definida no escopo global pode acessar todas as variáveis definidas no escopo global. A função definida dentro de outra função também pode acessar todas as variáveis definidas na função hospedeira e outras variáveis ao qual a função hospedeira tem acesso.

- -
// As seguintes variáveis são definidas no escopo global
-var num1 = 20,
-    num2 = 3,
-    nome = "Chamahk";
-
-// Esta função é definida no escopo global
-function multiplica() {
-  return num1 * num2;
-}
-
-multiplica(); // Retorna 60
-
-// Um exemplo de função aninhada
-function getScore () {
-  var num1 = 2,
-      num2 = 3;
-
-  function add() {
-    return nome + " scored " + (num1 + num2);
-  }
-
-  return add();
-}
-
-getScore(); // Retorna "Chamahk scored 5"
-
- -

Escopo e a pilha de função

- -

Recursão

- -

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

- -
    -
  1. o nome da função
  2. -
  3. arguments.callee
  4. -
  5. uma variável no escopo que se refere a função
  6. -
- -

Por exemplo, considere a seguinte definição de função:

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

Dentro do corpo da função, todos, a seguir, são equivalentes:

- -
    -
  1. bar()
  2. -
  3. arguments.callee()
  4. -
  5. foo()
  6. -
- -

Uma função que chama a si mesma é chamada de função recursiva. Em alguns casos, a recursividade é análoga a um laço. Ambos executam o código várias vezes, e ambos necessitam de uma condição (para evitar um laço infinito, ou melhor, recursão infinita, neste caso). Por exemplo,  o seguinte laço:

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

pode ser convertido em função recursiva e uma chamada para a função:

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

No entanto, alguns algoritmos não podem ser simples laços iterativos. Por exemplo, conseguir todos os nós da estrutura de uma árvore (por exemplo, o DOM) é mais fácil se feito recursivamente:

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

Em comparação ao laço da função, cada chamada recursiva realiza outras chamadas recursivas.

- -

É possível converter qualquer algoritmo recursivo para um não recursivo, mas muitas vezes a lógica é muito mais complexa e exige o uso de pilhas. Na verdade a própria recursão usa pilha: a pilha de função.

- -

O comportamento da pilha pode ser vista a seguir no exemplo:

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

que produz:

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

Funções aninhadas e closures

- -

Você pode aninhar uma função dentro de outra. A função aninhada (interna) é acessível apenas para a função que a contém (exterior). Isso constitui também uma closure. Uma closure é uma expressão (tipicamente uma função) que pode ter variáveis livres em conjunto com um ambiente que conecta estas variáveis (que "fecha" a expressão).

- -

Uma vez que uma função aninhada é uma closure, isto significa que uma função aninhada pode "herdar" os argumentos e variáveis de sua função de contenção. Em outras palavras, a função interior contém o escopo da função exterior.

- -

Em resumo:

- - - -

O exemplo a seguir mostra as funções aninhadas:

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

Uma vez que a função interna forma uma closure, você pode chamar a função externa e especificar argumentos para a função externa e interna:

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

Preservação  de variáveis

- -

Observe como x é preservado quando dentro é retornado. Uma closure deve preservar os argumentos e variáveis em todos os escopos que ela referencia. Uma vez que cada chamada fornece potencialmente argumentos diferentes, uma nova closure é criada para cada chamada de fora. A memória só poderá ser liberada quando o dentro retornado já não é mais acessível.

- -

Isso não é diferente de armazenar referências em outros objetos, mas muitas vezes é menos óbvio, porque um não define diretamente as referências e não pode inspecioná-las.

- -

Múltiplas funções aninhadas

- -

Funções podem ter múltiplo aninhamento, por exemplo, a função (A) contém a função (B) que contém a função (C). Tanto as funções B e C formam uma closure, então B pode acessar A, e C pode acessar B. Além disso, uma vez que C pode acessar B que pode acessar A, C também pode acessar A. Assim, a closure pode conter vários escopos; eles recursivamente contém o escopo das funções que os contém. Isso é chamado encadeamento de escopo. (O motivo de ser chamado "encadeamento" será explicado mais tarde).

- -

Considere o seguinte exemplo:

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

Neste exemplo, C acessa y do B e x do A. Isso pode ser feito porque:

- -
    -
  1. B forma uma closure incluindo A, isto é, B pode acessar argumentos e variáveis de A.
  2. -
  3. C forma uma closure incluindo B.
  4. -
  5.  Devido a closure B inclui A, a closure C inclui A, C pode acessar tanto argumentos e variáveis de B como de A. Em outras palavras, C encadeia o escopo de B e A, nesta ordem.
  6. -
- -

O inverso, no entanto, não é verdadeiro. A não pode acessar C, porque A não pode acessar qualquer argumento ou variável de B. Assim, C é privado somente a B.

- -

Conflitos de nome

- -

Quando dois argumentos ou variáveis nos escopos da closure tem o mesmo nome, há um conflito de nome. Mas escopos internos tem prioridade, por isso o escopo mais interno tem a maior prioridade, enquanto que o escopo mais externo tem a menor. Esta é a cadeia de escopo. O primeiro da cadeia é o escopo mais interno, e o último é o escopo mais externo. Considere o seguinte:

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

O  conflito de nome acontece na declaração return x e está entre o parâmetro x de dentro e a variável x de fora. A cadeia de escopo aqui é {dentro, fora, objeto global}. Por isso o x de dentro tem precedência sobre o x de fora, e 20 (x de dentro) é retornado em vez de 10 (x de fora).

- -

Closures

- -

Closures são um dos recursos mais poderosos de JavaScript. JavaScript permite o aninhamento de funções e garante acesso completo à função interna a todas as variáveis e funções definidas dentro da função externa (e todas as outras variáveis e funções que a função externa tem acesso). No entanto, a função externa não tem acesso às variáveis e funções definidas dentro da função interna. Isto proporciona uma espécie de segurança para as variáveis da função interna. Além disso, uma vez  que a função interna tem acesso ao escopo da função externa, as variáveis e funções definidas na função externa vão durar na memória mais do que a própria função externa, isto se a função interna permanecer na memória mais tempo do que a função externa. Uma closure é criada quando a função interna é de alguma forma disponibilizada para qualquer escopo fora da função externa.

- -
var pet = function(nome) {          // A função externa define uma variável "nome"
-      var getNome = function() {
-        return nome;                // A função interna tem acesso à variável "nome"  da função externa
-      }
-
-      return getNome;               // Retorna a função interna, expondo-a assim para escopos externos
-    },
-    myPet = pet("Vivie");
-
-myPet();                            // Retorna "Vivie"
-
- -

Ela pode ser  mais complexa que o código acima. Um objeto contendo métodos para manipular as variáveis da função externa pode ser devolvida.

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

Nos códigos acima, a variável nome da função externa é acessível para as funções internas, e não há nenhuma outra maneira para acessar as variáveis internas, exceto pelas funções internas. As variáveis internas da função interna atuam como armazenamento seguro para as funções internas. Elas armazenam "persistentes", mas seguros, os dados com os quais as funções internas irão trabalhar. As funções não tem  que ser atribuídas a uma variável, ou ter um nome.

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

Há, no entanto, uma série de armadilhas que se deve ter cuidado ao usar closures. Se uma função fechada define uma variável com o mesmo nome de uma variável em um escopo externo, não há nenhuma maneira de se referir para a variável em um escopo externo novamente.

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

A palavra reservada this é muito complicada em closures, elas têm de ser usadas com muito cuidado. O objeto ao que this se refere depende completamente de onde a função foi chamada, ao invés de onde ela foi definida.

- -

Usando objeto de argumentos

- -

Os argumentos de uma função são mantidos em um objeto do tipo array. Dentro de uma função, você pode endereçar os argumentos passados para ele conforme: 

- -
arguments[i]
-
- -

onde i é um número ordinal do argumento, começando com zero. Então, o primeiro argumento passado para a função seria arguments[0]. O número total de argumentos é indicado por arguments.length.

- -

Usando o objeto arguments, você pode chamar a função com mais argumentos do que o formalmente declarado. Isso muitas vezes é útil se você não sabe de antemão quantos argumentos serão passados para a função. Você pode usar arguments.length para determinar a quantidade de argumentos passados para a função, e então acessar cada argumento usando o objeto arguments.

- -

Por exemplo, considere uma função que concatena várias strings. O argumento formal para a função é uma string que especifica os caracteres que separam os itens para concatenar.  A função definida como segue:

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

Você pode passar qualquer quantidade de argumentos para esta função, e ela concatena cada argumento na string "list":

- -
// retorna "red, orange, blue, "
-myConcat(", ", "red", "orange", "blue");
-
-// retorna "elephant; giraffe; lion; cheetah; "
-myConcat("; ", "elephant", "giraffe", "lion", "cheetah");
-
-// retorna "sage. basil. oregano. pepper. parsley. "
-myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
-
- -
-

Nota: A variável arguments é "como um array", mas não é um array. Ela é como um array pois possui um índice numerado e a propriedade length. No entanto, não possui todos os métodos de manipulação de array. 

-
- -

Veja objeto {{jsxref("Function")}} na referência do JavaScript para maiores informações.

- -

Parâmetros de função

- -

Começando com ECMAScript 6, há dois tipos novos de parâmetros: parâmetros padrão e parâmetros rest.

- -

Parâmetros padrão

- -

Em JavaScript, parâmetros padrões de funções são undefined. No entanto, em algumas situações pode ser útil definir um valor padrão diferente. Isto é onde os parâmetros padrão podem ajudar.

- -

No passado, a estratégia geral para definir padrões era testar os valores de parâmetro no corpo da função e atribuir um valor se eles fossem undefined. Se, no exemplo a seguir, nenhum valor é fornecido para b na chamada, seu valor seria undefined ao avaliar a*b e a chamada para multiplicar retornaria NaN. No entanto, isso é pego com a segunda linha neste exemplo:

- -
function multiplicar(a, b) {
-  b = typeof b !== 'undefined' ?  b : 1;
-
-  return a*b;
-}
-
-multiplicar(5); // 5
- -

Com parâmetros padrão, a verificação no corpo da função não é mais necessária. Agora você pode simplesmente colocar 1 como valor padrão para b no campo de declaração de parâmetros:

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

Mais detalhes, consulte parâmetros padrão na referência.

- -

Parâmetros rest

- -

A sintaxe de parâmetro rest permite representar um número indefinido de argumentos como um array. No exemplo, usamos parâmetros rest para coletar argumentos do segundo argumento ao último. Então os multiplicamos pelo primeiro argumento. Neste exemplo é usado uma arrow function, que será introduzida na próxima seção.

- -
function multiplicar(multiplicador, ...args) {
-  return args.map(x => multiplicador * x);
-}
-
-var arr = multiplicar(2, 1, 2, 3);
-console.log(arr); // [2, 4, 6]
- -

Funções de seta

- -

Uma expressão função de seta (anteriormente conhecida como função de seta gorda) tem uma sintaxe pequena em comparação com a expressão de função e lexicalmente vincula o valor this. Funções de seta são sempre anônimas. Consulte também no blog hacks.mozilla.org no post: "ES6 In Depth: Arrow functions".

- -

Dois fatores influenciaram a introdução de funções de seta: funções mais curtas e o léxico this.

- -

Funções curtas

- -

Em alguns padrões funcionais, funções curtas são bem-vindas. Compare:

- -
var a = [
-  "Hydrogen",
-  "Helium",
-  "Lithium",
-  "Beryl­lium"
-];
-
-var a2 = a.map(function(s){ return s.length });
-
-var a3 = a.map( s => s.length );
- -

Léxico this

- -

Até as funções de seta, cada nova função definia seu próprio valor this (um novo objeto no caso de um construtor, indefinido em chamadas de função no modo estrito, o objeto de contexto se a função é chamada como um "método de objeto", etc.). Isso pode ser irritante com um estilo de programação orientada a objetos.

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

No ECMAScript 3/5, este problema foi resolvido atribuindo o valor em this a uma variável que poderia ser fechada.

- -
function Pessoa() {
-  var self = this; // Alguns preferem 'that' em vez de 'self'. 
-                   // Escolha um e seja consistente.
-  self.idade = 0;
-
-  setInterval(function crescer() {
-    // A chamada de retorno refere-se à variável 'self' na qual
-    // o valor é o objeto esperado.
-    self.idade++;
-  }, 1000);
-}
- -

Como alternativa, uma função vinculada poderia ser criada para que o valor da propriedade this seja passado para a função crescer().

- -

Funções de seta capturam o valor this do contexto delimitado, então o código a seguir funciona conforme o esperado.

- -
function Pessoa(){
-  this.idade = 0;
-
-  setInterval(() => {
-    this.idade++; // propriedade |this|refere ao objeto pessoa
-  }, 1000);
-}
-
-var p = new Pessoa();
- -

Funções pré-definidas

- -

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

- -
-
{{jsxref("Global_Objects/eval", "eval()")}}
-
-

O método eval() avalia código JavaScript representado como uma string.

-
-
{{jsxref("Global_Objects/uneval", "uneval()")}} {{non-standard_inline}}
-
-

O método uneval() cria uma representação de string do código-fonte de um  {{jsxref("Object")}}.

-
-
{{jsxref("Global_Objects/isFinite", "isFinite()")}}
-
-

A função global isFinite() determina se o valor passado é um número finito. Se necessário, o parâmetro é primeiro convertido para um número.

-
-
{{jsxref("Global_Objects/isNaN", "isNaN()")}}
-
-

A função isNaN() determina se um valor é {{jsxref("Global_Objects/NaN", "NaN")}} ou não. Nota: coerção dentro da função isNaN tem regras interessantes; você pode, alternativamente, querer usar {{jsxref("Number.isNaN()")}}, como definido no ECMAScript 6,  ou você pode usar typeof para determinar se o valor não é um número.

-
-
{{jsxref("Global_Objects/parseFloat", "parseFloat()")}}
-
-

A função parseFloat() analisa um argumento do tipo string e retorna um número de ponto flutuante.

-
-
{{jsxref("Global_Objects/parseInt", "parseInt()")}}
-
-

A função parseInt() analisa um argumento do tipo string e retorna um inteiro da base especificada (base do sistema numérico).

-
-
{{jsxref("Global_Objects/decodeURI", "decodeURI()")}}
-
-

A função decodeURI() decodifica uma Uniform Resource Identifier (URI) criada anteriormente por {{jsxref("Global_Objects/encodeURI", "encodeURI")}} ou por uma rotina similar.

-
-
{{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent()")}}
-
-

O método decodeURIComponent() decodifica um componente Uniform Resource Identifier (URI) criado anteriormente por {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} ou por uma rotina similar.

-
-
{{jsxref("Global_Objects/encodeURI", "encodeURI()")}}
-
-

O método encodeURI() codifica um Uniform Resource Identifier (URI), substituindo cada ocorrência de determinados caracteres por um, dois, três, ou quatro sequências de escape que representa a codificação UTF-8 do caractere (só serão quatro sequências de escape para caracteres compostos de dois caracteres "substitutos").

-
-
{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}}
-
-

O método encodeURIComponent() codifica um componente Uniform Resource Identifier (URI), substituindo cada ocorrência de determinados caracteres por um, dois, três, ou quatro sequências de escape que representa a codificação UTF-8 do caractere (só serão quatro sequências de escape para caracteres compostos de dois caracteres "substitutos").

-
-
{{jsxref("Global_Objects/escape", "escape()")}} {{deprecated_inline}}
-
-

O método obsoleto escape() calcula uma nova string na qual certos caracteres foram substituídos por uma sequência de escape hexadecimal. Use {{jsxref("Global_Objects/encodeURI", "encodeURI")}} ou {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} em vez disso.

-
-
{{jsxref("Global_Objects/unescape", "unescape()")}} {{deprecated_inline}}
-
-

O método obsoleto unescape() calcula uma nova string na qual sequências de escape hexadecimais são substituídas pelo caractere que ela representa. As sequências de escape podem ser introduzidas por uma função como {{jsxref("Global_Objects/escape", "escape")}}. Por unescape() estar obsoleto, use {{jsxref("Global_Objects/decodeURI", "decodeURI()")}} ou {{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent")}} ao invés dele.

-
-
- -

{{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}

diff --git a/files/pt-br/web/javascript/guide/grammar_and_types/index.html b/files/pt-br/web/javascript/guide/grammar_and_types/index.html new file mode 100644 index 0000000000..7920ee6b1a --- /dev/null +++ b/files/pt-br/web/javascript/guide/grammar_and_types/index.html @@ -0,0 +1,601 @@ +--- +title: Sintaxe e tipos +slug: 'Web/JavaScript/Guide/Values,_variables,_and_literals' +tags: + - Guia(2) + - Guía + - Iniciante + - JavaScript +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}

+ +

Este capítulo trata sobre a sintaxe básica do JavaScript, declarações de variáveis, tipos de dados e literais.

+ +

Sintaxe básica

+ +

JavaScript pega emprestado a maior parte de sua sintaxe do Java, mas também é influenciado por Awk, Perl e Python.

+ +

JavaScript é case-sensitive e usa o conjunto de caracteres Unicode. Por exemplo, a palavra Früh (que significa "cedo" em Alemão) pode ser usada como nome de variável.

+ +
var Früh = "foobar";
+ +

Mas a variável früh não é a mesma que Früh porque JavaScript é case sensitive.

+ +

No JavaScript, instruções são chamadas de {{Glossary("Statement", "declaração")}} e são separadas por um ponto e vírgula (;). Espaços, tabulação e uma nova linha são chamados de espaços em branco. O código fonte dos scripts em JavaScript são lidos da esquerda para a direita e são convertidos em uma sequência de elementos de entrada como simbolos, caracteres de controle, terminadores de linha, comentários ou espaço em branco. ECMAScript também define determinadas palavras-chave e literais, e tem regras para inserção automática de ponto e vírgula (ASI) para terminar as declarações. No entanto, recomenda-se sempre adicionar ponto e vírgula no final de suas declarações; isso evitará alguns imprevistos. Para obter mais informações, consulte a referência detalhada sobre a gramática léxica do JavaScript.

+ +

Comentários

+ +

A sintaxe dos comentários em JavaScript é semelhante como em C++ e em muitas outras linguagens:

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

Declarações

+ +

Existem três tipos de declarações em JavaScript.

+ +
+
{{jsxref("Statements/var", "var")}}
+
Declara uma variável, opcionalmente, inicializando-a com um valor.
+
{{experimental_inline}} {{jsxref("Statements/let", "let")}}
+
Declara uma variável local de escopo do bloco, opcionalmente, inicializando-a com um valor.
+
{{experimental_inline}} {{jsxref("Statements/const", "const")}}
+
Declara uma constante de escopo de bloco, apenas de leitura.
+
+ +

Variáveis

+ +

Você usa variáveis como nomes simbólicos para os valores em sua aplicação. O nome das variáveis, chamados de {{Glossary("Identifier", "identificadores")}}, obedecem determinadas regras.

+ +

Um identificador JavaScript deve começar com uma letra, underline (_), ou cifrão ($); os caracteres subsequentes podem também ser números (0-9). Devido JavaScript ser case-sensitive, letras incluem caracteres de "A" a "Z" (maiúsculos) e caracteres de "a" a "z" (minúsculos).

+ +

Você pode usar a ISO 8859-1 ou caracteres Unicode tal como os identificadores å e ü. Você pode também usar as sequências de escape Unicode como caracteres e identificadores.

+ +

Alguns exemplos de nomes legais são Numeros_visitas, temp99, e _nome.

+ +

Declarando variáveis

+ +

Você pode declarar uma variável de três formas:

+ + + +

Classificando variáveis

+ +

Uma variável declarada usando a declaração var ou let sem especificar o valor inicial tem o valor  {{jsxref("undefined")}}.

+ +

Uma tentativa de acessar uma variável não declarada resultará no lançamento de uma exceção {{jsxref("ReferenceError")}}:

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

Você pode usar undefined para determinar se uma variável tem um valor. No código a seguir, não é atribuído um valor de entrada na variável e a declaração if será avaliada como verdadeira (true).

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

O valor undefined se comporta como falso (false), quando usado em um contexto booleano. Por exemplo, o código a seguir executa a função myFunction devido o elemento myArray ser undefined:

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

O valor undefined converte-se para NaN quando usado no contexto numérico.

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

Quando você avalia uma variável nula, o valor nulo se comporta como 0 em contextos numéricos e como falso em contextos booleanos. Por exemplo:

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

Escopo de variável

+ +

Quando você declara uma váriavel fora de qualquer função, ela é chamada de variável global, porque está disponível para qualquer outro código no documento atual. Quando você declara uma variável dentro de uma função, é chamada de variável local,  pois ela está disponível somente dentro dessa função.

+ +

JavaScript antes do ECMAScript 6 não possuía escopo de declaração de bloco; pelo contrário, uma variável declarada dentro de um bloco de uma função é uma variável local (ou contexto global) do bloco que está inserido a função. Por exemplo o código a seguir exibirá 5, porque o escopo de x está na função (ou contexto global) no qual x é declarado, não o bloco, que neste caso é a declaração if

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

Esse comportamento é alterado, quando usado a declaração let introduzida pelo ECMAScript 6.

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

Variável de elevação

+ +

Outra coisa incomum sobre variáveis em JavaScript é que você pode utilizar a variável e declará-la depois, sem obter uma exceção. Este conceito é conhecido como hoisting; variáveis em JavaScript são num sentido "hoisted" ou lançada para o topo da função ou declaração. No entanto, as variáveis que são "hoisted" retornarão um valor undefined. Então, mesmo se você usar ou referir a variável e depois declará-la e inicializá-la, ela ainda retornará undefined.

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

Os exemplos acima serão interpretados como:

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

Devido o hoisting, todas as declarações var em uma função devem ser colocadas no início da função. Essa recomendação de prática deixa o código mais legível.

+ +

Variáveis Globais

+ +

Variáveis globais são propriedades do objeto global. Em páginas web o objeto global é a {{domxref("window")}}, assim você pode configurar e acessar variáveis globais utilizando a sintaxe window.variavel. 

+ +

Consequentemente, você pode acessar variáveis globais declaradas em uma janela ou frame ou frame de outra janela. Por exemplo, se uma variável chamada phoneNumber é declarada em um documento, você pode consultar esta variável de um frame como parent.phoneNumber.

+ +

Constantes

+ +

Você pode criar uma constante apenas de leitura por meio da palavra-chave {{jsxref("Statements/const", "const")}}. A sintaxe de um identificador de uma constante é semelhante ao identificador de uma variável: deve começar com uma letra, sublinhado ou cifrão e pode conter caractere alfabético, numérico ou sublinhado.

+ +
const PI = 3.14;
+
+ +

Uma constante não pode alterar seu valor por meio de uma atribuição ou ser declarada novamente enquanto o script está em execução. Deve ser inicializada com um valor.

+ +

As regras de escopo para as constantes são as mesmas para as váriaveis let de escopo de bloco. Se a palavra-chave const for omitida, presume-se que o identificador represente uma variável.

+ +

Você não pode declarar uma constante com o mesmo nome de uma função ou variável que estão no mesmo escopo. Por exemplo: 

+ +
// Isto irá causar um  erro
+function f() {};
+const f = 5;
+
+// Isto também irá causar um erro.
+function f() {
+  const g = 5;
+  var g;
+
+  //declarações
+}
+
+ +

Estrutura de dados e tipos

+ +

Tipos de dados

+ +

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

+ + + +

Embora esses tipos de dados sejam uma quantidade relativamente pequena, eles permitem realizar funções úteis em suas aplicações.  {{jsxref("Object", "Objetos")}} e {{jsxref("Function", "funções")}} são outros elementos fundamentais na linguagem. Você pode pensar em objetos como recipientes para os valores, e funções como métodos que suas aplicações podem executar.

+ +

Conversão de tipos de dados

+ +

JavaScript é uma linguagem dinamicamente tipada. Isso significa que você não precisa especificar o tipo de dado de uma variável quando declará-la, e tipos de dados são convertidos automaticamente conforme a necessidade durante a execução do script. Então, por exemplo, você pode definir uma variável da seguinte forma:

+ +
var answer = 42;
+
+ +

E depois, você pode atribuir uma string para a mesma variável, por exemplo:

+ +
answer = "Obrigado pelos peixes...";
+
+ +

Devido JavaScript ser dinamicamente tipado, essa declaração não gera uma mensagem de erro.

+ +

Em expressões envolvendo valores numérico e string com o operador +, JavaScript converte valores numérico para strings. Por exemplo, considere a seguinte declaração:

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

Nas declarações envolvendo outros operadores,  JavaScript não converte valores numérico para strings. Por exemplo:

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

Convertendo strings para números

+ +

No caso de um valor que representa um número está armazenado na memória como uma string, existem métodos para a conversão.

+ + + +

parseInt irá retornar apenas números inteiros, então seu uso é restrito para a casa dos decimais. Além disso, é uma boa prática ao usar parseInt incluir o parâmetro da base. O parâmetro da base é usado para especificar qual sistema númerico deve ser usado.

+ +

Uma método alternativo de conversão de um número em forma de string é com o operador + (operador soma):

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

Literais

+ +

Você usa literais para representar valores em JavaScript. Estes são valores fixados, não variáveis, que você literalmente insere em seu script. Esta seção descreve os seguintes tipos literais:

+ + + +

Array literal

+ +

Um array literal é uma lista de zero ou mais expressões, onde cada uma delas representam um elemento do array, inseridas entre colchetes ([]). Quando você cria um array usando um array literal, ele é inicializado  com os valores especificados como seus elementos, e seu comprimento é definido com o  número de elementos especificados.

+ +

O exemplo a seguir cria um array coffees com três elementos e um comprimento de três:

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

Nota : Um array literal é um tipo de inicializador de objetos. Veja Usando inicializadores de Objetos.

+
+ +

Se um array é criado usando um literal no topo do script, JavaScript interpreta o array cada vez que avalia a expressão que contêm o array literal. Além disso, um literal usado em uma função é criado cada vez que a função é chamada.

+ +

Array literal são também um array de objetos. Veja  {{jsxref("Array")}} e Coleções indexadas para detalhes sobre array de objetos.

+ +

Vírgulas extras em array literal

+ +

Você não precisa especificar todos os elementos em um array literal. Se você colocar duas vírgulas em uma linha, o array é criado com undefined para os elementos não especificados. O exemplo a seguir cria um array chamado fish:

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

Esse array tem dois elementos com valores e um elemento vazio (fish[0] é "Lion", fish[1] é undefined, e fish[2] é "Angel" ).

+ +

Se você incluir uma vírgula à direita no final da lista dos elementos, a vírgula é ignorada. No exemplo a seguir, o comprimento do array é três. Não há nenhum myList[3]. Todas as outras vírgulas na lista indicam um novo elemento.

+ +
+

Nota : Vírgulas à direita podem criar erros em algumas versões de navegadores web antigos, é recomendável removê-las.

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

No exemplo a seguir, o comprimento do array é quatro, e myList[0] e myList[2] são undefined.

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

No exemplo a seguir, o comprimento do array é quatro, e myList[1] e myList[3] são undefined. Apenas a última vírgula é ignorada.

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

Entender o comportamento de vírgulas extras é importante para a compreensão da linguagem JavaScript, no entanto, quando você escrever seu próprio código: declarar explicitamente os elementos em falta como undefined vai aumentar a clareza do código, e consequentemente na sua manutenção.

+ +

Literais Boolean

+ +

O tipo Boolean tem dois valores literal: true e false.

+ +

Não confunda os valores primitivos Boolean true e false com os valores true e false do objeto Boolean. O objeto Boolean é um invólucro em torno do tipo de dado primitivo. Veja {{jsxref("Boolean")}} para mais informação.

+ +

Inteiros

+ +

Inteiros podem ser expressos em decimal (base 10), hexadecimal (base 16), octal (base 8) e binário (base 2).

+ + + +

Alguns exemplos de inteiros literal são:

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

Para maiores informações, veja Literais numérico na referência Léxica.

+ +

Literais de ponto flutuante

+ +

Um literal de ponto flutuante pode ter as seguintes partes:

+ + + +

O expoente é um "e" ou "E" seguido por um inteiro, que pode ter sinal (precedido por "+" ou "-"). Um literal de ponto flutuante  deve ter no mínimo um dígito e um ponto decimal ou "e" (ou "E").

+ +

Mais sucintamente, a sintaxe é:

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

Por exemplo:

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

Objeto literal

+ +

Um objeto literal é uma lista de zero ou mais pares de nomes de propriedades e valores associados de um objeto, colocado entre chaves ({}). Você não deve usar um objeto literal no início de uma declaração. Isso levará a um erro ou não se comportará conforme o esperado, porque o { será interpretado como início de um bloco.

+ +

Segue um exemplo de um objeto literal. O primeiro elemento do objeto carro define uma propriedade, meuCarro, e atribui para ele uma nova string, "Punto"; o segundo elemento, a propriedade getCarro, é imediatamente atribuído o resultado de chamar uma função (tipoCarro("Fiat")); o terceiro elemento, a propriedade especial, usa uma variável existente (vendas).

+ +
var vendas = "Toyota";
+
+function tipoCarro(nome) {
+  if (nome == "Fiat") {
+    return nome;
+  } else {
+    return "Desculpa, não vendemos carros " + nome + ".";
+  }
+}
+
+var carro = { meuCarro: "Punto", getCarro: tipoCarro("Fiat"), especial: vendas };
+
+console.log(carro.meuCarro);   // Punto
+console.log(carro.getCarro);  // Fiat
+console.log(carro.especial); // Toyota
+
+ +

Além disso, você pode usar um literal numérico ou string para o nome de uma propriedade ou aninhar um objeto dentro do outro. O exemplo a seguir usar essas opções.

+ +
var carro = { carros: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };
+
+console.log(carro.carros.b); // Jeep
+console.log(carro[7]); // Mazda
+
+ +

Nomes de propriedades de objeto podem ser qualquer string, incluindo uma string vazia. Caso o nome da propriedade não seja um {{Glossary("Identifier","identificador")}} JavaScript ou número, ele deve ser colocado entre aspas. Nomes de propriedades que não possuem identificadores válido, também não podem ser acessadas pela propriedade de ponto (.), mas podem ser acessadas e definidas com a notação do tipo array ("[]").

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

Observe:

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

 

+ +

Expressão Regex Literal

+ +

Um regex literal é um padrão entre barras. A seguir um exemplo de regex literal.

+ +
var re = /ab+c/;
+ +

String Literal

+ +

Uma string literal são zero ou mais caracteres dispostos em aspas duplas (") ou aspas simples ('). Uma sequência de caracteres deve ser delimitada por aspas do mesmo tipo; ou seja,  as duas aspas simples ou ambas aspas duplas. A seguir um exemplo de strings literais.

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

Você pode chamar qualquer um dos métodos do objeto string em uma string literal - JavaScript automaticamente converte a string literal para um objeto string temporário, chama o método, em seguida, descarta o objeto string temporário. Você também pode usar a propriedade String.length com uma string literal:

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

Você deve usar string literal, a não ser que você precise usar um objeto string. Veja {{jsxref("String")}} para detalhes sobre objetos de strings.

+ +

Uso de caracteres especiais em string

+ +

Além dos caracteres comuns, você também pode incluir caracteres especiais em strings, como mostrado no exemplo a seguir.

+ +
"uma linha \n outra linha"
+
+ +

A tabela a seguir lista os caracteres especiais que podem ser usados em strings no JavaScript.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tabela: Caracteres especiais no JavaScript
CaracterDescrição
\0Byte nulo
\bBackspace
\fAlimentador de formulário
\nNova linha
\rRetorno do carro
\tTabulação
\vTabulação vertical
\'Apóstrofo ou aspas simples
\"Aspas dupla
\\Caractere de barra invertida
\XXX +

Caractere com a codificação Latin-1 especificada por três dígitos octal XXX entre 0 e 377. Por exemplo, \251 é sequência octal para o símbolo de direitos autorais.

+
\xXX +

Caractere com a codificação Latin-1 especificada por dois dígitos hexadecimal XX entre 00 e FF. Por exemplo, \xA9 é a sequência hexadecimal para o símbolo de direitos autorais.

+
\uXXXX +

Caractere Unicode especificado por quatro dígitos hexadecimal XXXX. Por exemplo, \u00A9 é a sequência Unicode para o símbolo de direitos autorais. Veja sequências de escape Unicode.

+
+ +

Caracteres de escape

+ +

Para caracteres não listados na tabela, se precedidos de barra invertida ela é ignorada, seu uso está absoleto e deve ser ignorado.

+ +

Você pode inserir uma aspa dentro de uma string precendendo-a com uma barra invertida. Isso  é conhecido como escaping das aspas. Por exemplo:

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

O resultado disso seria:

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

Para incluir uma barra invertida dentro de uma string, você deve escapar o caractere de barra invertida. Por exemplo, para atribuir o caminho do arquivo c:\temp para uma string, utilize o seguinte:

+ +
var home = "c:\\temp";
+
+ +

Você também pode escapar quebras de linhas, precedendo-as com barra invertida. A barra invertida e a quebra de linha são ambas removidas da string.

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

Embora JavaScript não tenha sintaxe "heredoc", você pode adicionar uma quebra de linha e um escape de quebra de linha no final de cada linha:

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

Mais informação

+ +

Este capítulo focou na sintaxe básica das declarações e tipos. Para saber mais sobre a linguagem JavaScript, veja também os seguintes capítulos deste guia:

+ + + +

No próximo capítulo, veremos a construção de controle de fluxos e manipulação de erro.

+ +

{{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}

diff --git a/files/pt-br/web/javascript/guide/igualdade/index.html b/files/pt-br/web/javascript/guide/igualdade/index.html deleted file mode 100644 index 57f1c2fdcc..0000000000 --- a/files/pt-br/web/javascript/guide/igualdade/index.html +++ /dev/null @@ -1,259 +0,0 @@ ---- -title: Igualdade em JavaScript -slug: Web/JavaScript/Guide/Igualdade -translation_of: Web/JavaScript/Equality_comparisons_and_sameness -translation_of_original: Web/JavaScript/Guide/Sameness ---- -

A ES6 possui três facilidades internas para determinar se algum x e algum y são "os mesmos". Elas são: igualdade ou "igual duplo" (==), igualdade rigorosa ou "igual triplo" (===), e Object.is. (Note que Object.is foi adicionado na ES6. Ambos igual duplo e igual triplo existiam antes da ES6, e seu comportamento permanece o mesmo.)

-

Visão geral

-

Para demonstração, aqui estão as três comparações de igualdade em uso:

-
x == y
-
x === y
-
Object.is(x, y)
-

De modo breve, o operador igual duplo irá realizar uma conversão de tipo na hora de  comparar duas coisas; o operador igual triplo fará a mesma comparação sem conversão de tipo (simplesmente sempre retornando false se os tipos forem diferentes); e Object.is se comportará da mesma forma que o operador igual triplo, mas lidando de forma especial com NaN e -0 e +0 de modo que os dois últimos não são considerados os mesmos, enquanto que Object.is(NaN, NaN) será true. (Comparar NaN com NaN geralmente—i.e., usando-se o operador igual duplo ou o operador igual triplo—resulta em false, de acordo com a IEEE 754.)

-

Note que a distinção entre todas essas formas de comparação tem a ver com a forma com que lidam com primitivos; nenhuma delas compara se os parâmetros são conceitualmente similares em estrutura. Para quaisquer objetos não-primitivos x e y que têm a mesma estrutura mas que são objetos distintos, todas as formas de comparação acima resultarão no valor false.

-

Por exemplo:

-
let x = { value: 17 };
-let y = { value: 17 };
-console.log(Object.is(x, y)); // false;
-console.log(x === y);         // false
-console.log(x == y);          // false
-

Igualdade abstrata, igualdade rigorosa, e mesmo valor

-

Na ES5, a comparação realizada por == é descrita na Seção 11.9.3, O Algoritmo de Igualdade Abstrata. A comparação === é descrita em 11.9.6, O Algoritmo de Igualdade Rigorosa. (Dê uma olhada nestes. Eles são rápidos e legíveis. Dica: leia o algoritmo de igualdade rigorosa primeiro.) A ES5 também descreve, na Seção 9.12, O Algoritmo de MesmoValor para ser usado internamente pelo engine JS. Ele é em sua maioria similar ao Algoritmo de Igualdade Rigorosa, com exceção de que 11.9.6.4 e 9.12.4 diferem na forma de lidar com Numbers (números). A ES6 simplesmente propõe expôr esse algoritmo através de Object.is.

-

Podemos ver que com os operadores igual duplo e igual triplo, com a exceção de fazer uma checagem de tipo de início em 11.9.6.1, o Algoritmo de Igualdade Rigorosa é um subconjunto do Algoritmo de Igualdade Abstrata, pois 11.9.6.2–7 corresponde a 11.9.3.1.a–f.

-

Um modelo para entender comparações de igualdade?

-

Antes da ES6, você pode ter dito, a respeito dos operadores igual duplo e igual triplo, que um é uma versão "melhorada" do outro. Por exemplo, alguém poderia dizer que o operador igual duplo é uma versão extendidad do operador igual triplo, pois o primeiro faz tudo que o último faz, com conversão de tipo em seus operandos (por exemplo, de modo que 6 == "6"). Alternativamente, alguém poderia dizer que o operador igual triplo é uma versão melhorada do operador igual duplo, pois requer que os dois operandos sejam do mesmo tipo. Qual é melhor depende de qual é a sua idéia de patamar.

-

No entanto, essa forma de pensar sobre os operados de igualdade internos não é um modelo que pode ser "esticado" para permitir um lugar para o Object.is da ES6 nesse "espectro". O Object.is não é simplesmente "menos restrito" do que o operador igual duplo ou "mais restrito" do que o operador igual triplo, nem cabe em algum lugar entre esses níveis (isto é, sendo mais restrito que o operador igual duplo, mas menos restrito que o operador igual triplo). Nós podemos ver da tabela de comparações de igualdade abaixo que isto é devido à forma com que Object.is lida com NaN. Perceba que se Object.is(NaN, NaN) resultasse no valor false, nós poderíamos dizer que ele cabe no espectro pouco restrito/restrito como uma forma ainda mais restrita do operador igual triplo, uma que faz distinção entre -0 e +0. A forma de lidar com NaN significa que isso não é verdade, no entanto. Infelizmente, Object.is simplesmente deve ser considerado em termos de duas características específicas, ao invés de sua rigorosidade (ou falta da mesma) com respeito aos operadores de igualdade.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Comparações de Igualdade
xy=====Object.is
undefinedundefinedtruetruetrue
nullnulltruetruetrue
truetruetruetruetrue
falsefalsetruetruetrue
"foo""foo"truetruetrue
{ foo: "bar" }xtruetruetrue
00truetruetrue
+0-0truetruefalse
0falsetruefalsefalse
""falsetruefalsefalse
""0truefalsefalse
"0"0truefalsefalse
"17"17truefalsefalse
new String("foo")"foo"truefalsefalse
nullundefinedtruefalsefalse
nullfalsefalsefalsefalse
undefinedfalsefalsefalsefalse
{ foo: "bar" }{ foo: "bar" }falsefalsefalse
new String("foo")new String("foo")falsefalsefalse
0nullfalsefalsefalse
0NaNfalsefalsefalse
"foo"NaNfalsefalsefalse
NaNNaNfalsefalsetrue
-

Quando usar Object.is versus o operador igual triplo

-

Além da forma com que trata o valor it NaN, de modo geral, o único caso em o comportamento especial de Object.is com a relação a zeros é capaz de ser de interesse é na busca de certos esquemas de metaprogramação, especialmente em relação a descritores de propriedade quando é desejável que seu trabalho espelhe algumas das características de Object.defineProperty. Se seu caso de uso não requer isso, sugere-se evitar-se Object.is e usar-se o operador === ao invés disso. Mesmo se seus requerimentos envolvem que comparações entre dois valores NaN resultem em true, de modo geral é mais fácil fazer-se uma checagem especial por NaNs (usando-se o método isNaN disponíveis de versões anteritores da ECMAScript) do que lidar com como computações externas possam afetar o sinal de quaisquer zeros que você possa encontrar em sua comparação.

-

Aqui está uma lista não-exaustiva de métodos e operadores internos que podem fazer com que uma distinção entre -0 e +0 se manifeste em seu código:

-
-
- - (negação unária)
-
-
-
-

É óbvio que negar 0 produz -0. Mas a abstração de uma expressão pode fazer com o valor -0 apareça de modo despercebido. Por exemplo, considere o seguinte:

-
let stoppingForce = obj.mass * -obj.velocity
-

Se obj.velocity é 0 (ou resulta no valor 0), um -0 é introduzido naquele ponto e propaga-se para stoppingForce.

-
-
-
-
- Math.atan2
-
- Math.ceil
-
- Math.pow
-
- Math.round
-
-
-
- É possível que um -0 seja introduzido em uma expressão como um valor de retorno desses métodos em alguns casos, mesmo quando nenhum -0 existe como um dos parâmetros. Por exemplo, usando-se Math.pow para elevar o valor -Infinity à potência de qualquer expoente negativo ímpar resulta no valor -0. Veja a documentação para os métodos individuais.
-
-
-
- Math.floor
-
- Math.max
-
- Math.min
-
- Math.sin
-
- Math.sqrt
-
- Math.tan
-
-
-
- É possível obter-se um valor de retorno -0 desses métodos em alguns casos quando um -0 existe como um dos parâmetros. Por exemplo, Math.min(-0, +0) resulta no valor -0. Veja a documentação para os métodos individuais.
-
-
-
- ~
-
- <<
-
- >>
-
- Cada um desses operadores usa o algoritmo ToInt32 internamente. Uma vez que só há uma representação para o valor 0 no tipo inteiro de 32 bits interno, o valor -0 não irá sobreviver a um arredondamento depois de uma operação inversa. Por exemplo, ambos Object.is(~~(-0), -0) e Object.is(-0 << 2 >> 2, -0) resultam no valor false.
-
-

Contar com Object.is quando o sinal de zeros não é levado em consideração pode ser problemático. É claro que quando a intenção é distinguir entre -0 e +0, ele faz exatamente o que é desejado.gual

diff --git a/files/pt-br/web/javascript/guide/inheritance_and_the_prototype_chain/index.html b/files/pt-br/web/javascript/guide/inheritance_and_the_prototype_chain/index.html deleted file mode 100644 index d6aad53066..0000000000 --- a/files/pt-br/web/javascript/guide/inheritance_and_the_prototype_chain/index.html +++ /dev/null @@ -1,193 +0,0 @@ ---- -title: Herança e cadeia de protótipos (prototype chain) -slug: Web/JavaScript/Guide/Inheritance_and_the_prototype_chain -tags: - - herança intermediário JavaScript OOP -translation_of: Web/JavaScript/Inheritance_and_the_prototype_chain ---- -
{{jsSidebar("Advanced")}}
- -

JavaScript é um pouco confuso para desenvolvedores com experiência em linguagens baseadas em classes (como Java ou C++), porque é dinâmico e não dispõe de uma implementação de uma class (a palavra-chave class foi introduzida no ES2015, mas é syntax sugar, o JavaScript permanece baseado em prototype).

- -

Quando se trata de herança, o JavaScript tem somente um construtor: objetos. Cada objeto tem um link interno para um outro objeto chamado prototype. Esse objeto prototype também tem um atributo prototype, e assim por diante até o que o valor null seja encontrado como sendo o seu prototype. null que, por definição, não tem prototype, e age como um link final nesta cadeia de protótipos (prototype chain).

- -

Isto muitas vezes é considerado como um dos pontos fracos do JavaScript, mas o modelo de herança prototipal é de fato mais potente do que o modelo clássico. É, por exemplo, relativamente trivial construir um "modelo clássico" (como na implementaçao de class), enquanto o contrário é uma tarefa muito mais difícil.

- -

N. da T: Como em uma implementação de fila em C, por exemplo.

- -

Herança com o encadeamento de protótipos

- -

Propriedades de heranças

- -

Objetos em JavaScript são "sacos" dinâmicos de propriedades (a que se refere as próprias propriedades) e cada um tem um link para um objeto prototype. Eis o que acontece quando se tenta acessar uma propriedade:

- -
// Vamos criar um objeto o da função f com suas próprias propriedades a e b:
-let f = function () {
-   this.a = 1;
-   this.b = 2;
-}
-let o = new f(); // {a: 1, b: 2}
-
-// adicionar propriedades no protótipo da função f
-f.prototype.b = 3;
-f.prototype.c = 4;
-
-// não defina o protótipo f.prototype = {b: 3, c: 4}; isso vai quebrar a cadeia de protótipos
-// o. [[Prototype]] possui propriedades bec.
-// o. [[Prototype]]. [[Prototype]] é Object.prototype.
-// Finalmente, o. [[Prototype]]. [[Prototype]]. [[Prototype]] é nulo.
-// Este é o fim da cadeia de protótipos, como nulo,
-// por definição, não possui [[Prototype]].
-// Assim, a cadeia completa de protótipos se parece com:
-// {a: 1, b: 2} ---> {b: 3, c: 4} ---> Object.prototype ---> null dfdf
-
-console.log(o.a); // 1
-// Existe uma propriedade 'a' no objeto o? Sim, e seu valor é 1.
-
-console.log(o.b); // 2
-// Existe uma propriedade própria 'b' em o? Sim, e seu valor é 2.
-// O protótipo também tem uma propriedade 'b', mas não é visitado.
-// Isso é chamado de sombreamento de propriedade(Property Shadowing)
-
-console.log(o.c); // 4
-// Existe uma propriedade própria 'c' em o? Não, verifique seu protótipo.
-// Existe uma propriedade 'c' própria em o. [[Prototype]]? Sim, seu valor é 4.
-
-console.log(o.d); // undefined
-// Existe uma propriedade 'd' própria em o? Não, verifique seu prototype.
-// Existe uma propriedade 'd' em o. [[Prototype]]? Não, verifique seu prototype.
-// o. [[Prototype]]. [[Prototype]] é Object.prototype e não há propriedade 'd' por padrão, verifique seu prototype.
-// o. [[Prototype]]. [[Prototype]]. [[Prototype]] é nulo, pare de pesquisar,
-// nenhuma propriedade encontrada, retorne indefinido.
-
- -

Code Link

- -

Atribuir uma propriedade a um objeto cria uma propriedade nele. A única exceção às regras de obtenção e definição de comportamento é quando há uma propriedade herdada com um getter or a setter.

- -

Herença de "métodos"

- -

JavaScript não tem "métodos" como os que conhecemos em linguagens baseadas em classes. Em JavaScript, qualquer função pode ser adicionada em um objeto em forma de propriedade. Uma herança de funções age como a herança de quaisquers outras propriedades que não sejam funções, e podemos inclusive realizar sobre-escrita de função(method overriding)!

- -

Quando uma herança de função é executada, o valor de this aponta para o objeto que herdou as propriedades, não para o objeto prototype onde as propriedades foram escritas originalmente.

- -
var o = {
-  a: 2,
-  m: function(b){
-    return this.a + 1;
-  }
-};
-
-console.log(o.m()); // 3
-// Ao chamar 'o.m' neste caso, "this" refere-se a 'o'
-
-var p = Object.create(o);
-// 'p' é um objeto que foi herdado de 'o'
-
-p.a = 12; // cria uma propriedade 'a' no objeto 'p'
-console.log(p.m()); // 13
-// Ao chamar 'p.m', 'this' refere-se a 'p'
-// Então, quando 'p' herda a função de 'm' de 'o', 'this.a' representa 'p.a' que é a própria propriedade 'a' de 'p'
-
-
- -

Maneiras de criar objetos e resultados dos protótipos encadeados

- -

Objetos criados com sintaxe de construtores

- -
var o = {a: 1};
-
-// O recém-criado objecto 'o' tem Object.prototype como o seu [[Prototype]]
-// 'o' não tem não tem uma propriedade chamada 'hasOwnProperty'
-// hasOwnProperty é uma propriedade própria de Object.prototype. Então 'o' herda hasOwnProperty de Object.prototype
-
-// Object.prototype tem null como seu protótipo.
-// o ---> Object.prototype ---> null
-
-var a = ["yo", "whadup", "?"];
-
-// Arrays herdam de Array.prototype (que tem métodos como indexOf, forEach, etc.)
-// A cadeia de protótipos se parece com isso:
-// a ---> Array.prototype ---> Object.prototype ---> null
-
-function f(){
-  return 2;
-}
-
-// Funções herdam de Function.prototype (que tem métodos como call, bind, etc.)
-// f ---> Function.prototype ---> Object.prototype ---> null
-
- -

Com um construtor

- -

Um "construtor" em JavaScript é "somente" uma função que passa a ser chamada com o operador new.

- -
function Graph() {
-  this.vertexes = [];
-  this.edges = [];
-}
-
-Graph.prototype = {
-  addVertex: function(v){
-    this.vertexes.push(v);
-  }
-};
-
-var g = new Graph();
-// 'g' é um objeto com as propriedades 'vertexes' e 'edges'.
-// g.[[Prototype]] é o valor de Graph.prototype quando new Graph() é executada.
-
- -

Com Object.create

- -

ECMAScript 5 introduziu o novo método: Object.create. Invocando este método podemos criar novos objetos. O prototype destes novos objetos é o primeiro argumento do método:

- -
var a = {a: 1};
-// a ---> Object.prototype ---> null
-
-var b = Object.create(a);
-// b ---> a ---> Object.prototype ---> null
-console.log(b.a); // 1 (inherited)
-
-var c = Object.create(b);
-// c ---> b ---> a ---> Object.prototype ---> null
-
-var d = Object.create(null);
-// d ---> null
-console.log(d.hasOwnProperty); // undefined, porque não herda de Object.prototype
-
- -
-

Performace

- -

O tempo de pesquisa para as propriedades que estão no alto da cadeia de protótipos pode ter um impacto negativo no desempenho, e isso pode ser significativo no código em que o desempenho é crítico. Além disso, tentando acessar propriedades inexistentes vai sempre atravessar a cadeia cheia do protótipo (full prototype chain).

- -

Porém, quando estamos interagindo com as propriedades de um objeto, toda propriedade que está na cadeia do prototype (prototype chain) vai ser enumerada.

- -

Para verificar se um objeto tem uma propriedade definida em si mesmo e não em algum lugar na sua cadeia de protótipo, é necessário usar o método hasOwnProperty que todos os objetos herdam do Object.prototype.

- -

hasOwnProperty é a única alternativa em JavaScript que lida com propriedades sem atravessar a cadeia de protótipos.

- - -
Observação: Não é suficiente apenas verificar se o valor da propriedade é undefined para saber se ela existe. A propriedade pode muito bem existir e não ter sido inicializada, sendo assim o seu valor undefined.
- -
-

Má Pratica: Estender protótipos nativos

- -

Um erro frequentemente cometido por programadores é estender um Object.prototype.

- -

Esta técnica é chamada de "monkey patching" e quebra o encapsulamento. Não existe uma boa razão para desorganizar tipos nativos do JavaScript para adicionar uma nova funcionalidade ao mesmo. 

- -

O único bom motivo para estender um protótipo nativo do JavaScript é para dar suporte a novas "features" do JavaScript; por exemplo: Array.forEach, etc.

-
- -
-

Conclusão

- -

É essencial entender bem  "prototypal inheritance" antes de escrever códigos complexos. Tome cuidado com o tamanho da sua cadeia de protótipos, quebre a cadeia caso necessário para evitar problemas de performace. Nunca estenda protótipos nativos a menos que seja para conseguir compatibilidade com novas "features" do JavaScript.

- - -
-
- -

{{ languages( {"zh-cn": "zh-cn/JavaScript/Guide/Inheritance_and_the_prototype_chain" } ) }}

diff --git a/files/pt-br/web/javascript/guide/iteratores_e_geradores/index.html b/files/pt-br/web/javascript/guide/iteratores_e_geradores/index.html deleted file mode 100644 index 13a9b87f11..0000000000 --- a/files/pt-br/web/javascript/guide/iteratores_e_geradores/index.html +++ /dev/null @@ -1,161 +0,0 @@ ---- -title: Iteratores e geradores -slug: Web/JavaScript/Guide/Iteratores_e_geradores -tags: - - Generators - - Guia(2) - - Intermediario(2) - - Iteradores - - JavaScript -translation_of: Web/JavaScript/Guide/Iterators_and_Generators ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Meta_programming")}}
- -

Processar cada item em uma coleção é uma operação muito comum. O JavaScript disponibiliza uma série de maneiras de iterar sobre uma coleção, desde um simples laço {{jsxref("Statements/for","for")}}, até um {{jsxref("Global_Objects/Array/map","map()")}} e também com o {{jsxref("Global_Objects/Array/filter","filter()")}}. Iteradores e Geradores trazem o conceito da interação ocorrer diretamente no núcleo da linguagem e prover um mecanismo para a customização do comportamento dos laços {{jsxref("Statements/for...of","for...of")}}.

- -

Para detalhes, também veja:

- - - -

Iterators (Iteradores)

- -

Um objeto é um iterator (iterador) quando sabe como acessar itens numa coleção, um por vez, enquanto mantém rastreada a posição atual em uma dada sequência. Em JavaScript um iterator é um objeto que oferece o método next(), o qual retorna o próximo item da sequência. Este método retorna um objeto com duas propriedades: done e value.

- -

Uma vez criado, um objeto iterator pode ser usado explicitamente ao chamar repetidas vezes o método next().

- -
const makeIterator = (array) => {
-
-let nextIndex = 0;
-
-return {
- next : () => {
-   return nextIndex < array.length ?
-    {value: array[nextIndex ++], done: false} :
-    {done: true};
-   }
- }
-};
- -

Uma vez inicializado, o método next() pode ser chamado para acessar os pares chave/valor do objeto da vez.

- -
let it = makeIterator(['yo', 'ya']);
-console.log(it.next().value); // 'yo'
-console.log(it.next().value); // 'ya'
-console.log(it.next().done);  // true
- -

Iterables (Iteráveis)

- -

Um objeto é iterável (iterable), se ele define seu comportamento de iteração, como no caso de quais valores percorridos em um laço do tipo {{jsxref("Statements/for...of", "for..of")}}. Alguns tipos embutidos, como o {{jsxref("Array")}}, ou o {{jsxref("Map")}}, têm um comportamento iterável padrão, enquanto outros tipos (como o{{jsxref("Object")}}) não possuem.

- -

Para que um objeto seja iterable, o objeto precisa implemntar o método @@iterator, significando que o objeto (ou um dos objetos na cadeia de prototipagem  - prototype chain) precisa ter uma propriedade com uma chave {{jsxref("Symbol.iterator")}}:

- -

Iterables definidos pelo usuário

- -

Nós podemos fazer, criar, os nossos próprios iteráveis como aqui:

- -
var myIterable = {}
-myIterable[Symbol.iterator] = function* () {
-    yield 1;
-    yield 2;
-    yield 3;
-};
-[...myIterable] // [1, 2, 3]
-
- -

Iterables Built-in (Iteráveis Embutidos)

- -

{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}} e {{jsxref("Set")}} são iteráveis embutidos, pois o protótipo dos objetos de todos eles têm o método {{jsxref("Symbol.iterator")}}.

- -

Syntaxes expecting iterables

- -

Algumas declarações e expressões esperam por iteradores, por exemplo o {{jsxref("Statements/for...of","for-of")}} loops, {{jsxref("Operators/Spread_operator","spread operator","","true")}}, {{jsxref("Operators/yield*","yield*")}}, e {{jsxref("Operators/Destructuring_assignment","destructuring assignment","","true")}}.

- -
for(let value of ["a", "b", "c"]){
-    console.log(value)
-}
-// "a"
-// "b"
-// "c"
-
-[..."abc"] // ["a", "b", "c"]
-
-function* gen(){
-  yield* ["a", "b", "c"]
-}
-
-gen().next() // { value:"a", done:false }
-
-[a, b, c] = new Set(["a", "b", "c"])
-a // "a"
-
-
- -

Generators

- -

Enquanto os iteradores são ferramentas muito úteis, sua criação requer um cuidado devido a necessidade de manter explicito seu estado interno. {{jsxref("Global_Objects/Generator","Generators","","true")}} provê uma alternativa poderosa: eles te permitem definir um algorítimo iterativo escrevendo uma função simples que pode manter seu estado próprio.

- -

Generator é um tipo especial de função que trabalha como uma factory para iteradores. A função vira um generator se ela contém uma ou mais expressões {{jsxref("Operators/yield","yield")}} e se ela usa a sintaxe {{jsxref("Statements/function*","function*")}}.

- -
function* idMaker(){
-  var index = 0;
-  while(true)
-    yield index++;
-}
-
-var gen = idMaker();
-
-console.log(gen.next().value); // 0
-console.log(gen.next().value); // 1
-console.log(gen.next().value); // 2
-// ...
- -

Generators avançados

- -

Generators computam seus valores "yielded" por demanda, que os permitem representar sequencias de forma eficiente que costumam ser trabalhosas ao serem computadas, ou até sequencias infinitas como demonstradas acima.

- -

O método {{jsxref("Global_Objects/Generator/next","next()")}} também aceita um valor que pode ser usado para modificar o estado interno de um generator. O valor passado pro next() será tratado como o resultado da última expressão yield que pausou o generator.

- -

Aqui um gerador de sequencia fibonacci usando next(x) pra restartar a sequencia:

- -
function* fibonacci(){
-  var fn1 = 1;
-  var fn2 = 1;
-  while (true){
-    var current = fn2;
-    fn2 = fn1;
-    fn1 = fn1 + current;
-    var reset = yield current;
-    if (reset){
-        fn1 = 1;
-        fn2 = 1;
-    }
-  }
-}
-
-var sequence = fibonacci();
-console.log(sequence.next().value);     // 1
-console.log(sequence.next().value);     // 1
-console.log(sequence.next().value);     // 2
-console.log(sequence.next().value);     // 3
-console.log(sequence.next().value);     // 5
-console.log(sequence.next().value);     // 8
-console.log(sequence.next().value);     // 13
-console.log(sequence.next(true).value); // 1
-console.log(sequence.next().value);     // 1
-console.log(sequence.next().value);     // 2
-console.log(sequence.next().value);     // 3
- -
Nota: Como um ponto de interesse, chamando next(undefined) é o mesmo que chamar next(). Entretanto, estartar um novo generator com qualquer valor que não seja undefined na chamada next() terá TypeError exception.
- -

Você pode forçar um generator a lançar uma exceção chamando o seu método {{jsxref("Global_Objects/Generator/throw","throw()")}}  e passando o valor da exceção que ele deve lançar. Essa exceção será lançada do contexto suspenso atual do generator, como se o yield atualmente suspenso fosse um throw.

- -

Se um yield não for encontrado durante o processo de lançamento de um thrown exception, então o exception será propagado através da chamada do throw(), e pra subsequente chamada do next() que terá a propriedade done resultando em true.

- -

Generators tem o método {{jsxref("Global_Objects/Generator/return","return(value)")}} que retorna o valor pego e finaliza o generator.

- -

{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Meta_programming")}}

diff --git a/files/pt-br/web/javascript/guide/iterators_and_generators/index.html b/files/pt-br/web/javascript/guide/iterators_and_generators/index.html new file mode 100644 index 0000000000..13a9b87f11 --- /dev/null +++ b/files/pt-br/web/javascript/guide/iterators_and_generators/index.html @@ -0,0 +1,161 @@ +--- +title: Iteratores e geradores +slug: Web/JavaScript/Guide/Iteratores_e_geradores +tags: + - Generators + - Guia(2) + - Intermediario(2) + - Iteradores + - JavaScript +translation_of: Web/JavaScript/Guide/Iterators_and_Generators +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Meta_programming")}}
+ +

Processar cada item em uma coleção é uma operação muito comum. O JavaScript disponibiliza uma série de maneiras de iterar sobre uma coleção, desde um simples laço {{jsxref("Statements/for","for")}}, até um {{jsxref("Global_Objects/Array/map","map()")}} e também com o {{jsxref("Global_Objects/Array/filter","filter()")}}. Iteradores e Geradores trazem o conceito da interação ocorrer diretamente no núcleo da linguagem e prover um mecanismo para a customização do comportamento dos laços {{jsxref("Statements/for...of","for...of")}}.

+ +

Para detalhes, também veja:

+ + + +

Iterators (Iteradores)

+ +

Um objeto é um iterator (iterador) quando sabe como acessar itens numa coleção, um por vez, enquanto mantém rastreada a posição atual em uma dada sequência. Em JavaScript um iterator é um objeto que oferece o método next(), o qual retorna o próximo item da sequência. Este método retorna um objeto com duas propriedades: done e value.

+ +

Uma vez criado, um objeto iterator pode ser usado explicitamente ao chamar repetidas vezes o método next().

+ +
const makeIterator = (array) => {
+
+let nextIndex = 0;
+
+return {
+ next : () => {
+   return nextIndex < array.length ?
+    {value: array[nextIndex ++], done: false} :
+    {done: true};
+   }
+ }
+};
+ +

Uma vez inicializado, o método next() pode ser chamado para acessar os pares chave/valor do objeto da vez.

+ +
let it = makeIterator(['yo', 'ya']);
+console.log(it.next().value); // 'yo'
+console.log(it.next().value); // 'ya'
+console.log(it.next().done);  // true
+ +

Iterables (Iteráveis)

+ +

Um objeto é iterável (iterable), se ele define seu comportamento de iteração, como no caso de quais valores percorridos em um laço do tipo {{jsxref("Statements/for...of", "for..of")}}. Alguns tipos embutidos, como o {{jsxref("Array")}}, ou o {{jsxref("Map")}}, têm um comportamento iterável padrão, enquanto outros tipos (como o{{jsxref("Object")}}) não possuem.

+ +

Para que um objeto seja iterable, o objeto precisa implemntar o método @@iterator, significando que o objeto (ou um dos objetos na cadeia de prototipagem  - prototype chain) precisa ter uma propriedade com uma chave {{jsxref("Symbol.iterator")}}:

+ +

Iterables definidos pelo usuário

+ +

Nós podemos fazer, criar, os nossos próprios iteráveis como aqui:

+ +
var myIterable = {}
+myIterable[Symbol.iterator] = function* () {
+    yield 1;
+    yield 2;
+    yield 3;
+};
+[...myIterable] // [1, 2, 3]
+
+ +

Iterables Built-in (Iteráveis Embutidos)

+ +

{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}} e {{jsxref("Set")}} são iteráveis embutidos, pois o protótipo dos objetos de todos eles têm o método {{jsxref("Symbol.iterator")}}.

+ +

Syntaxes expecting iterables

+ +

Algumas declarações e expressões esperam por iteradores, por exemplo o {{jsxref("Statements/for...of","for-of")}} loops, {{jsxref("Operators/Spread_operator","spread operator","","true")}}, {{jsxref("Operators/yield*","yield*")}}, e {{jsxref("Operators/Destructuring_assignment","destructuring assignment","","true")}}.

+ +
for(let value of ["a", "b", "c"]){
+    console.log(value)
+}
+// "a"
+// "b"
+// "c"
+
+[..."abc"] // ["a", "b", "c"]
+
+function* gen(){
+  yield* ["a", "b", "c"]
+}
+
+gen().next() // { value:"a", done:false }
+
+[a, b, c] = new Set(["a", "b", "c"])
+a // "a"
+
+
+ +

Generators

+ +

Enquanto os iteradores são ferramentas muito úteis, sua criação requer um cuidado devido a necessidade de manter explicito seu estado interno. {{jsxref("Global_Objects/Generator","Generators","","true")}} provê uma alternativa poderosa: eles te permitem definir um algorítimo iterativo escrevendo uma função simples que pode manter seu estado próprio.

+ +

Generator é um tipo especial de função que trabalha como uma factory para iteradores. A função vira um generator se ela contém uma ou mais expressões {{jsxref("Operators/yield","yield")}} e se ela usa a sintaxe {{jsxref("Statements/function*","function*")}}.

+ +
function* idMaker(){
+  var index = 0;
+  while(true)
+    yield index++;
+}
+
+var gen = idMaker();
+
+console.log(gen.next().value); // 0
+console.log(gen.next().value); // 1
+console.log(gen.next().value); // 2
+// ...
+ +

Generators avançados

+ +

Generators computam seus valores "yielded" por demanda, que os permitem representar sequencias de forma eficiente que costumam ser trabalhosas ao serem computadas, ou até sequencias infinitas como demonstradas acima.

+ +

O método {{jsxref("Global_Objects/Generator/next","next()")}} também aceita um valor que pode ser usado para modificar o estado interno de um generator. O valor passado pro next() será tratado como o resultado da última expressão yield que pausou o generator.

+ +

Aqui um gerador de sequencia fibonacci usando next(x) pra restartar a sequencia:

+ +
function* fibonacci(){
+  var fn1 = 1;
+  var fn2 = 1;
+  while (true){
+    var current = fn2;
+    fn2 = fn1;
+    fn1 = fn1 + current;
+    var reset = yield current;
+    if (reset){
+        fn1 = 1;
+        fn2 = 1;
+    }
+  }
+}
+
+var sequence = fibonacci();
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+console.log(sequence.next().value);     // 3
+console.log(sequence.next().value);     // 5
+console.log(sequence.next().value);     // 8
+console.log(sequence.next().value);     // 13
+console.log(sequence.next(true).value); // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+console.log(sequence.next().value);     // 3
+ +
Nota: Como um ponto de interesse, chamando next(undefined) é o mesmo que chamar next(). Entretanto, estartar um novo generator com qualquer valor que não seja undefined na chamada next() terá TypeError exception.
+ +

Você pode forçar um generator a lançar uma exceção chamando o seu método {{jsxref("Global_Objects/Generator/throw","throw()")}}  e passando o valor da exceção que ele deve lançar. Essa exceção será lançada do contexto suspenso atual do generator, como se o yield atualmente suspenso fosse um throw.

+ +

Se um yield não for encontrado durante o processo de lançamento de um thrown exception, então o exception será propagado através da chamada do throw(), e pra subsequente chamada do next() que terá a propriedade done resultando em true.

+ +

Generators tem o método {{jsxref("Global_Objects/Generator/return","return(value)")}} que retorna o valor pego e finaliza o generator.

+ +

{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Meta_programming")}}

diff --git a/files/pt-br/web/javascript/guide/lacos_e_iteracoes/index.html b/files/pt-br/web/javascript/guide/lacos_e_iteracoes/index.html deleted file mode 100644 index fcf7437612..0000000000 --- a/files/pt-br/web/javascript/guide/lacos_e_iteracoes/index.html +++ /dev/null @@ -1,333 +0,0 @@ ---- -title: Laços e iterações -slug: Web/JavaScript/Guide/Lacos_e_iteracoes -translation_of: Web/JavaScript/Guide/Loops_and_iteration ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}
- -
-

Laços oferecem um jeito fácil e rápido de executar uma ação repetidas vezes. Este capítulo do guia do JavaScript abordará diferentes formas de iterações existentes no JavaScript.

-
- -

Você pode pensar em um laço de repetição como um jogo onde você manda o seu personagem andar X passos em uma direção e Y passos em outra; por exemplo, a ideia "vá 5 passos para leste" pode ser expressa em um laço desta forma:

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

Existem várias formas diferentes de laços, mas eles essencialmente fazem a mesma coisa: repetir uma ação múltiplas vezes ( inclusive você poderá repetir 0 vezes). Os vários mecanismos diferentes de laços oferecem diferentes formas de determinar quando este irá começar ou terminar. Há várias situações em que é mais fácil resolver um problema utilizando um determinado tipo de laço do que outros.

- -

Os possíveis laços de repetição  em JavaScript:

- - - -

Declaração for

- -

Um laço for é repetido até que a condição especificada seja falsa. O laço for no JavaScript é similar ao Java e C. Uma declaração for é feita da seguinte maneira:

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

Quando um for é executado, ocorre o seguinte:

- -
    -
  1. A expressão expressao Inicial é inicializada e, caso possível, é executada. Normalmente essa expressão inicializa um ou mais contadores, mas a sintaxe permite expressões de qualquer grau de complexidade. Podendo conter também declaração de variáveis.
  2. -
  3. A expressão condicao é avaliada. caso o resultado de condicao seja verdadeiro, o laço é executado. Se o valor de condicao é falso, então o laço terminará. Se a expressão condicao é omitida, a condicao é assumida como verdadeira.
  4. -
  5.  A instrução é executada. Para executar múltiplas declarações, use uma declaração em bloco ({ ... }) para agrupá-las.
  6. -
  7. A atualização da expressão incremento, se houver, executa, e retorna o controle para o passo 2.
  8. -
- -

Exemplo

- -

A função a seguir contém uma declaração for que contará o número de opções selecionadas em uma lista (um elemento {{HTMLElement("select")}} permite várias seleções). Dentro do for é declarado uma váriavel i inicializada com zero. A declaração for verifica se i é menor que o número de opções no elemento <select>, executa sucessivas declaração  if, e incrementa i de um em um a cada passagem pelo laço.

- -
<form name="selectForm">
-  <p>
-    <label for="tipoMusica">Escolha alguns tipos de música, em seguida, clique no botão abaixo:</label>
-    <select id="tipoMusica" name="tipoMusica" multiple="multiple">
-      <option selected="selected">R&B</option>
-      <option>Jazz</option>
-      <option>Blues</option>
-      <option>New Age</option>
-      <option>Classico</option>
-      <option>Ópera</option>
-    </select>
-  </p>
-  <p><input id="btn" type="button" value="Quantos foram selecionados?" /></p>
-</form>
-
-<script>
-function howMany(selectObject) {
-  var numeroSelecionadas = 0;
-  for (var i = 0; i < selectObject.options.length; i++) {
-    if (selectObject.options[i].selected) {
-      numeroSelecionadas++;
-    }
-  }
-  return numeroSelecionadas;
-}
-
-var btn = document.getElementById("btn");
-btn.addEventListener("click", function(){
-  alert('Total de opções selecionadas: ' + howMany(document.selectForm.tipoMusica))
-});
-</script>
-
-
- -

Declaração do...while

- -

A instrução do...while repetirá até que a condição especificada seja falsa.

- -
do
-  declaracao
-while (condicao);
-
- -

A instrução será executada uma vez antes da condição ser verificada. Para executar multiplas instruções utilize uma declaração de bloco ({ ... }) para agrupá-las. Caso a condicao seja verdadeira, então o laço será executado novamente. Ao final de cada execução, a condicao é verificada. Quando a condição contida no while for falsa a execução do laço é terminada e o controle é passado para a instrução seguinte a do...while.

- -

Exemplo

- -

No exemplo a seguir, o laço é executado pelo menos uma vez e irá executar até que i seja menor que 5.

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

Declaração while

- -

Uma declaração while executa suas instruções, desde que uma condição especificada seja avaliada como verdadeira. Segue uma declaração while

- -
while (condicao)
-  declaracao
-
- -

Se a condição se tornar falsa,  a declaração dentro do laço para a execução e o controle é passado para a instrução após o laço.

- -

O teste da condição ocorre antes que o laço seja executado. Desta forma se a condição for verdadeira o laço executará e testará a condição novamente. Se a condição for falsa o laço termina e passa o controle para as instruções após o laço.

- -

Para executar múltiplas declarações, use uma declaração em bloco ({ ... }) para agrupar essas declarações.

- -

Exemplo 1

- -

O while a seguir executará enquanto n for menor que três:

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

A cada iteração, o laço incrementa n e adiciona este valor para x. Portanto, x e n recebem os seguintes valores:

- - - -

Depois de executar pela terceira vez, a condição n < 3 não será mais verdadeira, então o laço encerrará.

- -

Exemplo 2

- -

Evite laços infinitos. Tenha certeza que a condição do laço eventualmente será falsa; caso contrário, o laço nunca terminará. O while a seguir executará para sempre pois sua condição nunca será falsa:

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

Declaração label

- -

Um label provê um identificador que permite que este seja referenciado em outro lugar no seu programa. Por exemplo, você pode usar uma label para identificar um laço, e então usar break ou continue para indicar quando o programa deverá interromper o laço ou continuar sua execução.

- -

Segue a sintaxe da instrução label:

- -
label : declaracao
-
- -

Um label pode usar qualquer idenficador que não seja uma palavra reservada do JavaScript. Você pode identificar qualquer instrução com um label.

- -

Exemplo

- -

Neste exemplo, o label markLoop idenfica um laço while.

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

Declaração break

- -

Use break para terminar laços, switch, ou um conjunto que utiliza label.

- - - -

Segue a sintaxe do break:

- -
    -
  1. break;
  2. -
  3. break label;
  4. -
- -

Na primeira opção será encerrado o laço de repetição mais interno ou switch. Já na segunda opção será encerrada o bloco de código referente a label.

- -

Exemplo 1

- -

O exemplo a seguir percorre os elementos de um array até que ele encontre o índice do elemento que possui o valor contido em theValue:

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

Exemplo 2: Utilizando break em label

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

Declaração continue

- -

A declaração continue pode ser usada para reiniciar uma instrução while, do-while, for, ou label.

- - - -

Segue a sintaxe do continue:

- -
    -
  1. continue;
  2. -
  3. continue label;
  4. -
- -

Exemplo 1

- -

O exemplo a seguir mostra um laço while utlizando continue que executará quando o valor de i for igual a 3. Desta forma, n recebe os valores um, três, sete, e doze.

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

Exemplo 2

- -

Uma instrução label checkiandj contém uma instrução label checkj. Se o continue for executado, o programa terminará a iteração atual de checkj e começará a próxima iteração. Toda vez que o continue for executado, checkj recomeçará até que a condição do while for falsa. Quando isto ocorrer checkiandj executará até que sua condição seja falsa.

- -

Se o continue estivesse referenciando checkiandj, o programa deveria continuar do topo de checkiandj.

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

Declaração for...in

- -

A declaração for...in executa iterações a partir de uma variável específica, percorrendo todas as propriedades de um objeto.
- Para cada propriedade distinta, o JavaScript executará uma iteração. Segue a sintaxe:

- -
for (variavel in objeto) {
-  declaracoes
-}
-
- -

Exemplo

- -

A função a seguir recebe em seu argumento um objeto e o nome deste objeto. Então executará uma iteração para cada elemento e retornará uma lista de string, que irá conter o nome da propriedade e seu valor.

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

Para um objeto chamado car com propriedades make e model, o resultado será:

- -
car.make = Ford
-car.model = Mustang
-
- -

Arrays

- -

Embora seja tentador usar esta forma para interagir com os elementos de um Array, a declaração for...in irá retornar o nome pré-definido da propriedade ao invés do seu index numérico. Assim é melhor usar o tradicional for com index numérico quando interagir com arrays, pois o for...in interage com as propriedades definidas pelo programador ao invés dos elementos do array.

- -

Declaração for...of

- -

 A declaração for...of cria uma laço com objetos interativos ((incluindo, {{jsxref("Array")}}, {{jsxref("Map")}}, {{jsxref("Set")}}, assim por conseguinte ), executando uma iteração para o valor de cada propriedade distinta.

- -
for (variavel of objeto) {
-  declaracoes
-}
- -

O exemplo a seguir mostra a diferença entre o for...of e o for...in. Enquanto o for...in interage com o nome das propriedades, o for...of interage com o valor das propriedades.

- -
let arr = [3, 5, 7];
-arr.foo = "hello";
-
-for (let i in arr) {
-   console.log(i); // logs "0", "1", "2", "foo"
-}
-
-for (let i of arr) {
-   console.log(i); // logs "3", "5", "7"
-}
-
- -

{{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}

diff --git a/files/pt-br/web/javascript/guide/loops_and_iteration/index.html b/files/pt-br/web/javascript/guide/loops_and_iteration/index.html new file mode 100644 index 0000000000..fcf7437612 --- /dev/null +++ b/files/pt-br/web/javascript/guide/loops_and_iteration/index.html @@ -0,0 +1,333 @@ +--- +title: Laços e iterações +slug: Web/JavaScript/Guide/Lacos_e_iteracoes +translation_of: Web/JavaScript/Guide/Loops_and_iteration +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}
+ +
+

Laços oferecem um jeito fácil e rápido de executar uma ação repetidas vezes. Este capítulo do guia do JavaScript abordará diferentes formas de iterações existentes no JavaScript.

+
+ +

Você pode pensar em um laço de repetição como um jogo onde você manda o seu personagem andar X passos em uma direção e Y passos em outra; por exemplo, a ideia "vá 5 passos para leste" pode ser expressa em um laço desta forma:

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

Existem várias formas diferentes de laços, mas eles essencialmente fazem a mesma coisa: repetir uma ação múltiplas vezes ( inclusive você poderá repetir 0 vezes). Os vários mecanismos diferentes de laços oferecem diferentes formas de determinar quando este irá começar ou terminar. Há várias situações em que é mais fácil resolver um problema utilizando um determinado tipo de laço do que outros.

+ +

Os possíveis laços de repetição  em JavaScript:

+ + + +

Declaração for

+ +

Um laço for é repetido até que a condição especificada seja falsa. O laço for no JavaScript é similar ao Java e C. Uma declaração for é feita da seguinte maneira:

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

Quando um for é executado, ocorre o seguinte:

+ +
    +
  1. A expressão expressao Inicial é inicializada e, caso possível, é executada. Normalmente essa expressão inicializa um ou mais contadores, mas a sintaxe permite expressões de qualquer grau de complexidade. Podendo conter também declaração de variáveis.
  2. +
  3. A expressão condicao é avaliada. caso o resultado de condicao seja verdadeiro, o laço é executado. Se o valor de condicao é falso, então o laço terminará. Se a expressão condicao é omitida, a condicao é assumida como verdadeira.
  4. +
  5.  A instrução é executada. Para executar múltiplas declarações, use uma declaração em bloco ({ ... }) para agrupá-las.
  6. +
  7. A atualização da expressão incremento, se houver, executa, e retorna o controle para o passo 2.
  8. +
+ +

Exemplo

+ +

A função a seguir contém uma declaração for que contará o número de opções selecionadas em uma lista (um elemento {{HTMLElement("select")}} permite várias seleções). Dentro do for é declarado uma váriavel i inicializada com zero. A declaração for verifica se i é menor que o número de opções no elemento <select>, executa sucessivas declaração  if, e incrementa i de um em um a cada passagem pelo laço.

+ +
<form name="selectForm">
+  <p>
+    <label for="tipoMusica">Escolha alguns tipos de música, em seguida, clique no botão abaixo:</label>
+    <select id="tipoMusica" name="tipoMusica" multiple="multiple">
+      <option selected="selected">R&B</option>
+      <option>Jazz</option>
+      <option>Blues</option>
+      <option>New Age</option>
+      <option>Classico</option>
+      <option>Ópera</option>
+    </select>
+  </p>
+  <p><input id="btn" type="button" value="Quantos foram selecionados?" /></p>
+</form>
+
+<script>
+function howMany(selectObject) {
+  var numeroSelecionadas = 0;
+  for (var i = 0; i < selectObject.options.length; i++) {
+    if (selectObject.options[i].selected) {
+      numeroSelecionadas++;
+    }
+  }
+  return numeroSelecionadas;
+}
+
+var btn = document.getElementById("btn");
+btn.addEventListener("click", function(){
+  alert('Total de opções selecionadas: ' + howMany(document.selectForm.tipoMusica))
+});
+</script>
+
+
+ +

Declaração do...while

+ +

A instrução do...while repetirá até que a condição especificada seja falsa.

+ +
do
+  declaracao
+while (condicao);
+
+ +

A instrução será executada uma vez antes da condição ser verificada. Para executar multiplas instruções utilize uma declaração de bloco ({ ... }) para agrupá-las. Caso a condicao seja verdadeira, então o laço será executado novamente. Ao final de cada execução, a condicao é verificada. Quando a condição contida no while for falsa a execução do laço é terminada e o controle é passado para a instrução seguinte a do...while.

+ +

Exemplo

+ +

No exemplo a seguir, o laço é executado pelo menos uma vez e irá executar até que i seja menor que 5.

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

Declaração while

+ +

Uma declaração while executa suas instruções, desde que uma condição especificada seja avaliada como verdadeira. Segue uma declaração while

+ +
while (condicao)
+  declaracao
+
+ +

Se a condição se tornar falsa,  a declaração dentro do laço para a execução e o controle é passado para a instrução após o laço.

+ +

O teste da condição ocorre antes que o laço seja executado. Desta forma se a condição for verdadeira o laço executará e testará a condição novamente. Se a condição for falsa o laço termina e passa o controle para as instruções após o laço.

+ +

Para executar múltiplas declarações, use uma declaração em bloco ({ ... }) para agrupar essas declarações.

+ +

Exemplo 1

+ +

O while a seguir executará enquanto n for menor que três:

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

A cada iteração, o laço incrementa n e adiciona este valor para x. Portanto, x e n recebem os seguintes valores:

+ + + +

Depois de executar pela terceira vez, a condição n < 3 não será mais verdadeira, então o laço encerrará.

+ +

Exemplo 2

+ +

Evite laços infinitos. Tenha certeza que a condição do laço eventualmente será falsa; caso contrário, o laço nunca terminará. O while a seguir executará para sempre pois sua condição nunca será falsa:

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

Declaração label

+ +

Um label provê um identificador que permite que este seja referenciado em outro lugar no seu programa. Por exemplo, você pode usar uma label para identificar um laço, e então usar break ou continue para indicar quando o programa deverá interromper o laço ou continuar sua execução.

+ +

Segue a sintaxe da instrução label:

+ +
label : declaracao
+
+ +

Um label pode usar qualquer idenficador que não seja uma palavra reservada do JavaScript. Você pode identificar qualquer instrução com um label.

+ +

Exemplo

+ +

Neste exemplo, o label markLoop idenfica um laço while.

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

Declaração break

+ +

Use break para terminar laços, switch, ou um conjunto que utiliza label.

+ + + +

Segue a sintaxe do break:

+ +
    +
  1. break;
  2. +
  3. break label;
  4. +
+ +

Na primeira opção será encerrado o laço de repetição mais interno ou switch. Já na segunda opção será encerrada o bloco de código referente a label.

+ +

Exemplo 1

+ +

O exemplo a seguir percorre os elementos de um array até que ele encontre o índice do elemento que possui o valor contido em theValue:

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

Exemplo 2: Utilizando break em label

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

Declaração continue

+ +

A declaração continue pode ser usada para reiniciar uma instrução while, do-while, for, ou label.

+ + + +

Segue a sintaxe do continue:

+ +
    +
  1. continue;
  2. +
  3. continue label;
  4. +
+ +

Exemplo 1

+ +

O exemplo a seguir mostra um laço while utlizando continue que executará quando o valor de i for igual a 3. Desta forma, n recebe os valores um, três, sete, e doze.

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

Exemplo 2

+ +

Uma instrução label checkiandj contém uma instrução label checkj. Se o continue for executado, o programa terminará a iteração atual de checkj e começará a próxima iteração. Toda vez que o continue for executado, checkj recomeçará até que a condição do while for falsa. Quando isto ocorrer checkiandj executará até que sua condição seja falsa.

+ +

Se o continue estivesse referenciando checkiandj, o programa deveria continuar do topo de checkiandj.

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

Declaração for...in

+ +

A declaração for...in executa iterações a partir de uma variável específica, percorrendo todas as propriedades de um objeto.
+ Para cada propriedade distinta, o JavaScript executará uma iteração. Segue a sintaxe:

+ +
for (variavel in objeto) {
+  declaracoes
+}
+
+ +

Exemplo

+ +

A função a seguir recebe em seu argumento um objeto e o nome deste objeto. Então executará uma iteração para cada elemento e retornará uma lista de string, que irá conter o nome da propriedade e seu valor.

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

Para um objeto chamado car com propriedades make e model, o resultado será:

+ +
car.make = Ford
+car.model = Mustang
+
+ +

Arrays

+ +

Embora seja tentador usar esta forma para interagir com os elementos de um Array, a declaração for...in irá retornar o nome pré-definido da propriedade ao invés do seu index numérico. Assim é melhor usar o tradicional for com index numérico quando interagir com arrays, pois o for...in interage com as propriedades definidas pelo programador ao invés dos elementos do array.

+ +

Declaração for...of

+ +

 A declaração for...of cria uma laço com objetos interativos ((incluindo, {{jsxref("Array")}}, {{jsxref("Map")}}, {{jsxref("Set")}}, assim por conseguinte ), executando uma iteração para o valor de cada propriedade distinta.

+ +
for (variavel of objeto) {
+  declaracoes
+}
+ +

O exemplo a seguir mostra a diferença entre o for...of e o for...in. Enquanto o for...in interage com o nome das propriedades, o for...of interage com o valor das propriedades.

+ +
let arr = [3, 5, 7];
+arr.foo = "hello";
+
+for (let i in arr) {
+   console.log(i); // logs "0", "1", "2", "foo"
+}
+
+for (let i of arr) {
+   console.log(i); // logs "3", "5", "7"
+}
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}

diff --git a/files/pt-br/web/javascript/guide/modules/index.html b/files/pt-br/web/javascript/guide/modules/index.html new file mode 100644 index 0000000000..6a2cb73687 --- /dev/null +++ b/files/pt-br/web/javascript/guide/modules/index.html @@ -0,0 +1,454 @@ +--- +title: Módulos JavaScript +slug: Web/JavaScript/Guide/Módulos +translation_of: Web/JavaScript/Guide/Modules +--- +
{{JSSidebar("JavaScript Guide")}}{{Previous("Web/JavaScript/Guide/Meta_programming")}}
+ +

Este guia fornece tudo o que você precisa para começar com a sintaxe de módulo do JavaScript.

+ +

Um background em módulos

+ +

Os programas JavaScript começaram muito pequenos - a maior parte do seu uso nos primeiros dias era para executar tarefas isoladas de script, fornecendo um pouco de interatividade às suas páginas da Web sempre que necessário, de modo que scripts grandes geralmente não eram necessários. Com o avanço rápido da tecnologia agora temos aplicativos completos sendo executados em navegadores com muito JavaScript, além de JavaScript ser usado em outros contextos (Node.js, por exemplo).

+ +

Portanto, fez sentido nos últimos anos começar a pensar em fornecer mecanismos para dividir programas JavaScript em módulos separados que podem ser importados quando necessário. O Node.js possui essa capacidade há muito tempo e existem várias bibliotecas e estruturas JavaScript que permitem o uso do módulo (por exemplo, outros CommonJS e AMD-sistemas de módulos baseados em RequireJS, e mais recentemente Webpack e Babel).

+ +

A boa notícia é que os navegadores modernos começaram a dar suporte nativamente à funcionalidade do módulo, e é sobre isso que este artigo trata. Isso só pode ser uma coisa boa - os navegadores podem otimizar o carregamento de módulos, tornando-o mais eficiente do que ter que usar uma biblioteca e fazer todo esse processamento extra no lado do cliente e viagens de ida e volta extras.

+ +

Suporte do navegador

+ +

O uso de módulos JavaScript nativos depende do{{JSxRef("Statements/import", "import")}} e {{JSxRef("Statements/export", "export")}} afirmações; estes são suportados nos navegadores da seguinte maneira:

+ +

importa

+ +

{{Compat("javascript.statements.import")}}

+ +

exporta

+ +

{{Compat("javascript.statements.export")}}

+ +

Apresentando um exemplo

+ +

Para demonstrar o uso dos módulos, criamos um conjunto simples de exemplos que você pode encontrar no GitHub. Estes exemplos demonstram um conjunto simples de módulos que criam um<canvas> em uma página da Web e desenhe (e relate informações sobre) formas diferentes na tela.

+ +

Estes são bastante triviais, mas foram mantidos deliberadamente simples para demonstrar claramente os módulos.

+ +
+

Nota: Se você deseja fazer o download dos exemplos e executá-los localmente, precisará executá-los por meio de um servidor da web local.

+
+ +

Exemplo de uma estrutura básica

+ +

No nosso primeiro exemplo (consulte basic-modules) nós temos uma estrutura de arquivos da seguinte maneira:

+ +
index.html
+main.js
+modules/
+    canvas.js
+    square.js
+ +
+

Nota: Todos os exemplos neste guia têm basicamente a mesma estrutura; o exposto acima deve começar a ficar bem familiar.

+
+ +

Os dois módulos do diretório modules são descritos abaixo:

+ + + +

Aside — .mjs versus .js

+ +

Neste artigo, usamos extensões .js para nossos arquivos de módulo, mas em outros recursos você pode ver a extensão .mjs usada. A documentação da V8 recomenda isso, por exemplo. Os motivos apresentados são:

+ + + +

No entanto, decidimos continuar usando .js, pelo menos por enquanto. Para que os módulos funcionem corretamente em um navegador, você precisa garantir que seu servidor os esteja servindo com um cabeçalho Content-Type que contenha um tipo MIME JavaScript, como text / javascript. Caso contrário, você receberá um erro estrito de verificação do tipo MIME, de acordo com as linhas "O servidor respondeu com um tipo MIME não JavaScript" e o navegador não executará seu JavaScript. A maioria dos servidores já define o tipo correto para arquivos .js, mas ainda não para arquivos .mjs. Servidores que já veiculam arquivos .mjs incluem corretamente GitHub Pages e http-server para Node.js.

+ +

Tudo bem se você já estiver usando esse ambiente ou se não estiver, mas souber o que está fazendo e tiver acesso (ou seja, você pode configurar o servidor para definir a configuração correta Content-Type para arquivos .mjs). No entanto, isso pode causar confusão se você não controlar o servidor do qual está servindo arquivos ou publicar arquivos para uso público, como estamos aqui.

+ +

Para fins de aprendizado e portabilidade, decidimos manter o.js.

+ +

Se você realmente valoriza a clareza de usar .mjs para módulos versus usar .js para arquivos JavaScript "normais", mas não deseja se deparar com o problema descrito acima, sempre poderá usar .mjs durante o desenvolvimento e convertê-los em .js durante sua etapa de construção.

+ +

Também é importante notar que:

+ + + +

Exportando recursos do módulo

+ +

A primeira coisa que você faz para obter acesso aos recursos do módulo é exportá-los. Isso é feito usando o {{JSxRef("Statements/export", "export")}} declaração.

+ +

A maneira mais fácil de usá-lo é colocá-lo na frente de qualquer item que você queira exportar para fora do módulo, por exemplo:

+ +
export const name = 'square';
+
+export function draw(ctx, length, x, y, color) {
+  ctx.fillStyle = color;
+  ctx.fillRect(x, y, length, length);
+
+  return {
+    length: length,
+    x: x,
+    y: y,
+    color: color
+  };
+}
+ +

Você pode exportar funções, var, let, const, e — como veremos mais tarde - classes. Eles precisam ser itens de nível superior; você não pode usar a exportação dentro de uma função, por exemplo.

+ +

Uma maneira mais conveniente de exportar todos os itens que você deseja exportar é usar uma única instrução de exportação no final do arquivo do módulo, seguida por uma lista separada por vírgula dos recursos que você deseja exportar envoltos em chaves. Por exemplo:

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

Importando recursos para o seu script

+ +

Depois de exportar alguns recursos do seu módulo, é necessário importá-los para o script para poder usá-los. A maneira mais simples de fazer isso é a seguinte:

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
+ +

Você usa o {{JSxRef("Statements/import", "import")}} , seguida por uma lista separada por vírgula dos recursos que você deseja importar agrupados em chaves, seguidos pela palavra-chave de, seguida pelo caminho para o arquivo do módulo - um caminho relativo à raiz do site, que para nossa basic-modules exemplo seria/js-examples/modules/basic-modules.

+ +

No entanto, escrevemos o caminho de maneira um pouco diferente - estamos usando a sintaxe de ponto (.) Para significar "o local atual", seguido pelo caminho além do arquivo que estamos tentando encontrar. Isso é muito melhor do que escrever todo o caminho relativo a cada vez, pois é mais curto e torna o URL portátil - o exemplo ainda funcionará se você o mover para um local diferente na hierarquia do site.

+ +

Então, por exemplo:

+ +
/js-examples/modules/basic-modules/modules/square.js
+ +

torna-se

+ +
./modules/square.js
+ +

Você pode ver essas linhas em ação em main.js.

+ +
+

Nota: Em alguns sistemas de módulos, você pode omitir a extensão do arquivo e o ponto(e.g. '/modules/square'). Isso não funciona nos módulos JavaScript nativos.

+
+ +

Depois de importar os recursos para o seu script, você pode usá-los exatamente como eles foram definidos no mesmo arquivo. O seguinte é encontrado em
+ main.js, abaixo das linhas de importação:

+ +
let myCanvas = create('myCanvas', document.body, 480, 320);
+let reportList = createReportList(myCanvas.id);
+
+let square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
+reportArea(square1.length, reportList);
+reportPerimeter(square1.length, reportList);
+
+ +
+

Nota: Embora os recursos importados estejam disponíveis no arquivo, eles são visualizações somente leitura do recurso que foi exportado. Você não pode alterar a variável importada, mas ainda pode modificar propriedades semelhantes à const. Além disso, esses recursos são importados como ligações ativas, o que significa que eles podem mudar de valor mesmo que você não possa modificar a ligação ao contrário de const.

+
+ +

Aplicando o módulo ao seu HTML

+ +

Agora, apenas precisamos aplicar o módulo main.js. à nossa página HTML. Isso é muito semelhante ao modo como aplicamos um script regular a uma página, com algumas diferenças notáveis.

+ +

Primeiro de tudo, você precisa incluir type="module" no <script> elemento, para declarar esse script como um módulo. Para importar o main.js script, usamos este:

+ +
<script type="module" src="main.js"></script>
+ +

Você também pode incorporar o script do módulo diretamente no arquivo HTML, colocando o código JavaScript no corpo do elemento <script>:

+ +
<script type="module">
+  /* JavaScript module code here */
+</script>
+ +

O script para o qual você importa os recursos do módulo atua basicamente como o módulo de nível superior. Se você o omitir, o Firefox, por exemplo, exibirá um erro "SyntaxError: as declarações de importação podem aparecer apenas no nível superior de um módulo".

+ +

Você só pode usar import e export instruções dentro de módulos, não scripts regulares.

+ +

Outras diferenças entre módulos e scripts padrão

+ + + +

Exportações padrão versus exportações nomeadas

+ +

A funcionalidade que exportamos até agora foi composta por named exports — cada item (seja uma função, const, etc.) foi referido por seu nome na exportação e esse nome também foi usado para se referir a ele na importação.

+ +

Há também um tipo de exportação chamado default export — isso foi projetado para facilitar a função padrão fornecida por um módulo e também ajuda os módulos JavaScript a interoperar com os sistemas de módulos CommonJS e AMD existentes (conforme explicado em ES6 In Depth: Modules por Jason Orendorff; procure por "Exportações padrão").

+ +

Vejamos um exemplo ao explicar como ele funciona. Nos nossos módulos básicos square.js você pode encontrar uma função chamada randomSquare() que cria um quadrado com cor, tamanho e posição aleatórios. Queremos exportar isso como padrão, portanto, na parte inferior do arquivo, escrevemos isso:

+ +
export default randomSquare;
+ +

Note a falta dos colchetes.

+ +

Em vez disso, poderíamos acrescentar export default na função e defina-a como uma função anônima, assim:

+ +
export default function(ctx) {
+  ...
+}
+ +

No nosso arquivo main.js., importamos a função padrão usando esta linha:

+ +
import randomSquare from './modules/square.js';
+ +

Isso ocorre porque há apenas uma exportação padrão permitida por módulo e sabemos que randomSquare é isso.

+ +
import {default as randomSquare} from './modules/square.js';
+ +
+

Nota: A sintaxe as para renomear itens exportados é explicada abaixo no Renaming imports and exports seção.

+
+ +

Evitando conflitos de nomenclatura

+ +

Até agora, nossos módulos de desenho de forma de tela parecem estar funcionando bem. Mas o que acontece se tentarmos adicionar um módulo que lide com o desenho de outra forma, como um círculo ou triângulo? Essas formas provavelmente teriam funções associadas, como draw(), reportArea(), etc. também; se tentássemos importar diferentes funções com o mesmo nome para o mesmo arquivo de módulo de nível superior, acabaríamos com conflitos e erros.

+ +

Felizmente, existem várias maneiras de contornar isso. Veremos isso nas próximas seções.

+ +

Renomeando importações e exportações

+ +

Dentro dos colchetes da instrução de importação e exportação, você pode usar a palavra-chave junto com um novo nome de recurso, para alterar o nome de identificação que será usado para um recurso dentro do módulo de nível superior.

+ +

Por exemplo, os dois itens a seguir executariam o mesmo trabalho, embora de uma maneira ligeiramente diferente:

+ +
// inside module.js
+export {
+  function1 as newFunctionName,
+  function2 as anotherNewFunctionName
+};
+
+// inside main.js
+import { newFunctionName, anotherNewFunctionName } from './modules/module.js';
+ +
// inside module.js
+export { function1, function2 };
+
+// inside main.js
+import { function1 as newFunctionName,
+         function2 as anotherNewFunctionName } from './modules/module.js';
+ +

Vejamos um exemplo real. Na nossa renaming diretório, você verá o mesmo sistema de módulos do exemplo anterior, exceto que adicionamos circle.js e triangle.js módulos para desenhar e relatar círculos e triângulos.

+ +

Dentro de cada um desses módulos, temos recursos com os mesmos nomes sendo exportados e, portanto, cada um tem o mesmo export declaração na parte inferior:

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

Ao importá-los para o main.js, se tentarmos usar

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
+import { name, draw, reportArea, reportPerimeter } from './modules/circle.js';
+import { name, draw, reportArea, reportPerimeter } from './modules/triangle.js';
+ +

O navegador geraria um erro como "SyntaxError: redeclaration of import name" (Firefox).

+ +

Em vez disso, precisamos renomear as importações para que sejam únicas:

+ +
import { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter } from './modules/square.js';
+
+import { name as circleName,
+         draw as drawCircle,
+         reportArea as reportCircleArea,
+         reportPerimeter as reportCirclePerimeter } from './modules/circle.js';
+
+import { name as triangleName,
+        draw as drawTriangle,
+        reportArea as reportTriangleArea,
+        reportPerimeter as reportTrianglePerimeter } from './modules/triangle.js';
+ +

Observe que você pode resolver o problema nos arquivos do módulo, e.g.

+ +
// in square.js
+export { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter };
+ +
// in main.js
+import { squareName, drawSquare, reportSquareArea, reportSquarePerimeter } from './modules/square.js';
+ +

E funcionaria da mesma forma. Qual o estilo que você usa depende de você, no entanto, sem dúvida faz mais sentido deixar o código do módulo em paz e fazer as alterações nas importações. Isso faz especialmente sentido quando você está importando de módulos de terceiros sobre os quais você não tem controle.

+ +

24/5000

+ +

Criando um objeto de módulo

+ +

O método acima funciona bem, mas é um pouco confuso e longo. Uma solução ainda melhor é importar os recursos de cada módulo dentro de um objeto de módulo. O seguinte formulário de sintaxe faz isso:

+ +
import * as Module from './modules/module.js';
+ +

Isso captura todas as exportações disponíveis no module.js e as torna disponíveis como membros de um objeto Module, efetivamente dando o seu próprio namespace. Então, por exemplo:

+ +
Module.function1()
+Module.function2()
+etc.
+ +

Novamente, vejamos um exemplo real. Se você for ao nosso module-objects diretório, você verá o mesmo exemplo novamente, mas reescrito para aproveitar essa nova sintaxe. Nos módulos, as exportações são todas da seguinte forma simples:

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

As importações, por outro lado, são assim:

+ +
import * as Canvas from './modules/canvas.js';
+
+import * as Square from './modules/square.js';
+import * as Circle from './modules/circle.js';
+import * as Triangle from './modules/triangle.js';
+ +

Em cada caso, agora você pode acessar as importações do módulo abaixo do nome do objeto especificado, por exemplo:

+ +
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, 'blue');
+Square.reportArea(square1.length, reportList);
+Square.reportPerimeter(square1.length, reportList);
+ +

Agora você pode escrever o código da mesma forma que antes (contanto que inclua os nomes dos objetos quando necessário) e as importações sejam muito mais limpas.

+ +

Módulos e classes

+ +

Como sugerimos anteriormente, você também pode exportar e importar classes; essa é outra opção para evitar conflitos no seu código e é especialmente útil se você já tiver o código do módulo gravado em um estilo orientado a objetos.

+ +

Você pode ver um exemplo do nosso módulo de desenho de forma reescrito com as classes ES em nosso classes diretório. Como exemplo, o square.js O arquivo agora contém todas as suas funcionalidades em uma única classe:

+ +
class Square {
+  constructor(ctx, listId, length, x, y, color) {
+    ...
+  }
+
+  draw() {
+    ...
+  }
+
+  ...
+}
+ +

que exportamos então:

+ +
export { Square };
+ +

No main.js, nós o importamos assim:

+ +
import { Square } from './modules/square.js';
+ +

E então use a classe para desenhar nosso quadrado:

+ +
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+square1.draw();
+square1.reportArea();
+square1.reportPerimeter();
+ +

Módulos de agregação

+ +

Haverá momentos em que você desejará agregar módulos. Você pode ter vários níveis de dependências, nos quais deseja simplificar as coisas, combinando vários submódulos em um módulo pai. Isso é possível usando a sintaxe de exportação dos seguintes formulários no módulo pai:

+ +
export * from 'x.js'
+export { name } from 'x.js'
+ +

Por exemplo, veja nosso module-aggregation diretório. Neste exemplo (com base no exemplo de classes anteriores), temos um módulo extra chamado shapes.js, que agrega toda a funcionalidade de circle.js, square.js e triangle.js juntos. Também movemos nossos submódulos para dentro de um subdiretório dentro do diretório modules chamado shapes. Portanto, a estrutura do módulo neste exemplo é:

+ +
modules/
+  canvas.js
+  shapes.js
+  shapes/
+    circle.js
+    square.js
+    triangle.js
+ +

Em cada um dos submódulos, a exportação é da mesma forma, e.g.

+ +
export { Square };
+ +

Em seguida, vem a parte de agregação. Dentro de shapes.js, incluímos as seguintes linhas:

+ +
export { Square } from './shapes/square.js';
+export { Triangle } from './shapes/triangle.js';
+export { Circle } from './shapes/circle.js';
+ +

Eles capturam as exportações dos submódulos individuais e os disponibilizam efetivamente no módulo shapes.js.

+ +
+

Nota: As exportações mencionadas no shapes.js são basicamente redirecionadas pelo arquivo e realmente não existem nele, portanto, você não poderá escrever nenhum código relacionado útil dentro do mesmo arquivo.

+
+ +

Portanto, agora no arquivo main.js., podemos obter acesso às três classes de módulos substituindo

+ +
import { Square } from './modules/square.js';
+import { Circle } from './modules/circle.js';
+import { Triangle } from './modules/triangle.js';
+ +

com a seguinte linha única:

+ +
import { Square, Circle, Triangle } from './modules/shapes.js';
+ +

Carregamento dinâmico do módulo

+ +

A parte mais recente da funcionalidade dos módulos JavaScript a estar disponível nos navegadores é o carregamento dinâmico de módulos. Isso permite que você carregue módulos dinamicamente somente quando eles forem necessários, em vez de precisar carregar tudo antecipadamente. Isso tem algumas vantagens óbvias de desempenho; vamos ler e ver como isso funciona.

+ +

Essa nova funcionalidade permite que você ligue {{JSxRef("Statements/import", "import()", "#Dynamic_Imports")}} como uma função, passando o caminho para o módulo como um parâmetro. Retorna um{{JSxRef("Promise")}}, que cumpre com um objeto de módulo (consulte Creating a module object) dando acesso às exportações desse objeto, e.g.

+ +
import('./modules/myModule.js')
+  .then((module) => {
+    // Do something with the module.
+  });
+ +

Vejamos um exemplo. No dynamic-module-imports diretório, temos outro exemplo baseado em nosso exemplo de classes. Desta vez, no entanto, não estamos desenhando nada na tela quando o exemplo é carregado. Em vez disso, incluímos trêsbuttons — "Circle", "Square", e "Triangle" — que, quando pressionado, carrega dinamicamente o módulo necessário e, em seguida, usa-o para desenhar os shape.

+ +

Neste exemplo, fizemos apenas alterações em nossa index.html e main.js arquivos - as exportações do módulo permanecem as mesmas de antes.

+ +

No main.js, pegamos uma referência a cada botão usando umDocument.querySelector() chamada, por exemplo:

+ +
let squareBtn = document.querySelector('.square');
+ +

Em seguida, anexamos um ouvinte de evento a cada botão para que, quando pressionado, o módulo relevante seja carregado dinamicamente e usado para desenhar a forma(shape):

+ +
squareBtn.addEventListener('click', () => {
+  import('./modules/square.js').then((Module) => {
+    let square1 = new Module.Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+    square1.draw();
+    square1.reportArea();
+    square1.reportPerimeter();
+  })
+});
+ +

Observe que, como o cumprimento da promessa retorna um objeto de módulo, a classe é então transformada em uma sub-característica do objeto, portanto, agora precisamos acessar o construtor com Module. anexado a ele, e.g. Module.Square( ... ).

+ +

Solução de problemas

+ +

Aqui estão algumas dicas que podem ajudá-lo se você estiver com problemas para fazer seus módulos funcionarem. Sinta-se livre para adicionar à lista se descobrir mais!

+ + + +

Veja também

+ + + +

{{Previous("Web/JavaScript/Guide/Meta_programming")}}

diff --git "a/files/pt-br/web/javascript/guide/m\303\263dulos/index.html" "b/files/pt-br/web/javascript/guide/m\303\263dulos/index.html" deleted file mode 100644 index 6a2cb73687..0000000000 --- "a/files/pt-br/web/javascript/guide/m\303\263dulos/index.html" +++ /dev/null @@ -1,454 +0,0 @@ ---- -title: Módulos JavaScript -slug: Web/JavaScript/Guide/Módulos -translation_of: Web/JavaScript/Guide/Modules ---- -
{{JSSidebar("JavaScript Guide")}}{{Previous("Web/JavaScript/Guide/Meta_programming")}}
- -

Este guia fornece tudo o que você precisa para começar com a sintaxe de módulo do JavaScript.

- -

Um background em módulos

- -

Os programas JavaScript começaram muito pequenos - a maior parte do seu uso nos primeiros dias era para executar tarefas isoladas de script, fornecendo um pouco de interatividade às suas páginas da Web sempre que necessário, de modo que scripts grandes geralmente não eram necessários. Com o avanço rápido da tecnologia agora temos aplicativos completos sendo executados em navegadores com muito JavaScript, além de JavaScript ser usado em outros contextos (Node.js, por exemplo).

- -

Portanto, fez sentido nos últimos anos começar a pensar em fornecer mecanismos para dividir programas JavaScript em módulos separados que podem ser importados quando necessário. O Node.js possui essa capacidade há muito tempo e existem várias bibliotecas e estruturas JavaScript que permitem o uso do módulo (por exemplo, outros CommonJS e AMD-sistemas de módulos baseados em RequireJS, e mais recentemente Webpack e Babel).

- -

A boa notícia é que os navegadores modernos começaram a dar suporte nativamente à funcionalidade do módulo, e é sobre isso que este artigo trata. Isso só pode ser uma coisa boa - os navegadores podem otimizar o carregamento de módulos, tornando-o mais eficiente do que ter que usar uma biblioteca e fazer todo esse processamento extra no lado do cliente e viagens de ida e volta extras.

- -

Suporte do navegador

- -

O uso de módulos JavaScript nativos depende do{{JSxRef("Statements/import", "import")}} e {{JSxRef("Statements/export", "export")}} afirmações; estes são suportados nos navegadores da seguinte maneira:

- -

importa

- -

{{Compat("javascript.statements.import")}}

- -

exporta

- -

{{Compat("javascript.statements.export")}}

- -

Apresentando um exemplo

- -

Para demonstrar o uso dos módulos, criamos um conjunto simples de exemplos que você pode encontrar no GitHub. Estes exemplos demonstram um conjunto simples de módulos que criam um<canvas> em uma página da Web e desenhe (e relate informações sobre) formas diferentes na tela.

- -

Estes são bastante triviais, mas foram mantidos deliberadamente simples para demonstrar claramente os módulos.

- -
-

Nota: Se você deseja fazer o download dos exemplos e executá-los localmente, precisará executá-los por meio de um servidor da web local.

-
- -

Exemplo de uma estrutura básica

- -

No nosso primeiro exemplo (consulte basic-modules) nós temos uma estrutura de arquivos da seguinte maneira:

- -
index.html
-main.js
-modules/
-    canvas.js
-    square.js
- -
-

Nota: Todos os exemplos neste guia têm basicamente a mesma estrutura; o exposto acima deve começar a ficar bem familiar.

-
- -

Os dois módulos do diretório modules são descritos abaixo:

- - - -

Aside — .mjs versus .js

- -

Neste artigo, usamos extensões .js para nossos arquivos de módulo, mas em outros recursos você pode ver a extensão .mjs usada. A documentação da V8 recomenda isso, por exemplo. Os motivos apresentados são:

- - - -

No entanto, decidimos continuar usando .js, pelo menos por enquanto. Para que os módulos funcionem corretamente em um navegador, você precisa garantir que seu servidor os esteja servindo com um cabeçalho Content-Type que contenha um tipo MIME JavaScript, como text / javascript. Caso contrário, você receberá um erro estrito de verificação do tipo MIME, de acordo com as linhas "O servidor respondeu com um tipo MIME não JavaScript" e o navegador não executará seu JavaScript. A maioria dos servidores já define o tipo correto para arquivos .js, mas ainda não para arquivos .mjs. Servidores que já veiculam arquivos .mjs incluem corretamente GitHub Pages e http-server para Node.js.

- -

Tudo bem se você já estiver usando esse ambiente ou se não estiver, mas souber o que está fazendo e tiver acesso (ou seja, você pode configurar o servidor para definir a configuração correta Content-Type para arquivos .mjs). No entanto, isso pode causar confusão se você não controlar o servidor do qual está servindo arquivos ou publicar arquivos para uso público, como estamos aqui.

- -

Para fins de aprendizado e portabilidade, decidimos manter o.js.

- -

Se você realmente valoriza a clareza de usar .mjs para módulos versus usar .js para arquivos JavaScript "normais", mas não deseja se deparar com o problema descrito acima, sempre poderá usar .mjs durante o desenvolvimento e convertê-los em .js durante sua etapa de construção.

- -

Também é importante notar que:

- - - -

Exportando recursos do módulo

- -

A primeira coisa que você faz para obter acesso aos recursos do módulo é exportá-los. Isso é feito usando o {{JSxRef("Statements/export", "export")}} declaração.

- -

A maneira mais fácil de usá-lo é colocá-lo na frente de qualquer item que você queira exportar para fora do módulo, por exemplo:

- -
export const name = 'square';
-
-export function draw(ctx, length, x, y, color) {
-  ctx.fillStyle = color;
-  ctx.fillRect(x, y, length, length);
-
-  return {
-    length: length,
-    x: x,
-    y: y,
-    color: color
-  };
-}
- -

Você pode exportar funções, var, let, const, e — como veremos mais tarde - classes. Eles precisam ser itens de nível superior; você não pode usar a exportação dentro de uma função, por exemplo.

- -

Uma maneira mais conveniente de exportar todos os itens que você deseja exportar é usar uma única instrução de exportação no final do arquivo do módulo, seguida por uma lista separada por vírgula dos recursos que você deseja exportar envoltos em chaves. Por exemplo:

- -
export { name, draw, reportArea, reportPerimeter };
- -

Importando recursos para o seu script

- -

Depois de exportar alguns recursos do seu módulo, é necessário importá-los para o script para poder usá-los. A maneira mais simples de fazer isso é a seguinte:

- -
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
- -

Você usa o {{JSxRef("Statements/import", "import")}} , seguida por uma lista separada por vírgula dos recursos que você deseja importar agrupados em chaves, seguidos pela palavra-chave de, seguida pelo caminho para o arquivo do módulo - um caminho relativo à raiz do site, que para nossa basic-modules exemplo seria/js-examples/modules/basic-modules.

- -

No entanto, escrevemos o caminho de maneira um pouco diferente - estamos usando a sintaxe de ponto (.) Para significar "o local atual", seguido pelo caminho além do arquivo que estamos tentando encontrar. Isso é muito melhor do que escrever todo o caminho relativo a cada vez, pois é mais curto e torna o URL portátil - o exemplo ainda funcionará se você o mover para um local diferente na hierarquia do site.

- -

Então, por exemplo:

- -
/js-examples/modules/basic-modules/modules/square.js
- -

torna-se

- -
./modules/square.js
- -

Você pode ver essas linhas em ação em main.js.

- -
-

Nota: Em alguns sistemas de módulos, você pode omitir a extensão do arquivo e o ponto(e.g. '/modules/square'). Isso não funciona nos módulos JavaScript nativos.

-
- -

Depois de importar os recursos para o seu script, você pode usá-los exatamente como eles foram definidos no mesmo arquivo. O seguinte é encontrado em
- main.js, abaixo das linhas de importação:

- -
let myCanvas = create('myCanvas', document.body, 480, 320);
-let reportList = createReportList(myCanvas.id);
-
-let square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
-reportArea(square1.length, reportList);
-reportPerimeter(square1.length, reportList);
-
- -
-

Nota: Embora os recursos importados estejam disponíveis no arquivo, eles são visualizações somente leitura do recurso que foi exportado. Você não pode alterar a variável importada, mas ainda pode modificar propriedades semelhantes à const. Além disso, esses recursos são importados como ligações ativas, o que significa que eles podem mudar de valor mesmo que você não possa modificar a ligação ao contrário de const.

-
- -

Aplicando o módulo ao seu HTML

- -

Agora, apenas precisamos aplicar o módulo main.js. à nossa página HTML. Isso é muito semelhante ao modo como aplicamos um script regular a uma página, com algumas diferenças notáveis.

- -

Primeiro de tudo, você precisa incluir type="module" no <script> elemento, para declarar esse script como um módulo. Para importar o main.js script, usamos este:

- -
<script type="module" src="main.js"></script>
- -

Você também pode incorporar o script do módulo diretamente no arquivo HTML, colocando o código JavaScript no corpo do elemento <script>:

- -
<script type="module">
-  /* JavaScript module code here */
-</script>
- -

O script para o qual você importa os recursos do módulo atua basicamente como o módulo de nível superior. Se você o omitir, o Firefox, por exemplo, exibirá um erro "SyntaxError: as declarações de importação podem aparecer apenas no nível superior de um módulo".

- -

Você só pode usar import e export instruções dentro de módulos, não scripts regulares.

- -

Outras diferenças entre módulos e scripts padrão

- - - -

Exportações padrão versus exportações nomeadas

- -

A funcionalidade que exportamos até agora foi composta por named exports — cada item (seja uma função, const, etc.) foi referido por seu nome na exportação e esse nome também foi usado para se referir a ele na importação.

- -

Há também um tipo de exportação chamado default export — isso foi projetado para facilitar a função padrão fornecida por um módulo e também ajuda os módulos JavaScript a interoperar com os sistemas de módulos CommonJS e AMD existentes (conforme explicado em ES6 In Depth: Modules por Jason Orendorff; procure por "Exportações padrão").

- -

Vejamos um exemplo ao explicar como ele funciona. Nos nossos módulos básicos square.js você pode encontrar uma função chamada randomSquare() que cria um quadrado com cor, tamanho e posição aleatórios. Queremos exportar isso como padrão, portanto, na parte inferior do arquivo, escrevemos isso:

- -
export default randomSquare;
- -

Note a falta dos colchetes.

- -

Em vez disso, poderíamos acrescentar export default na função e defina-a como uma função anônima, assim:

- -
export default function(ctx) {
-  ...
-}
- -

No nosso arquivo main.js., importamos a função padrão usando esta linha:

- -
import randomSquare from './modules/square.js';
- -

Isso ocorre porque há apenas uma exportação padrão permitida por módulo e sabemos que randomSquare é isso.

- -
import {default as randomSquare} from './modules/square.js';
- -
-

Nota: A sintaxe as para renomear itens exportados é explicada abaixo no Renaming imports and exports seção.

-
- -

Evitando conflitos de nomenclatura

- -

Até agora, nossos módulos de desenho de forma de tela parecem estar funcionando bem. Mas o que acontece se tentarmos adicionar um módulo que lide com o desenho de outra forma, como um círculo ou triângulo? Essas formas provavelmente teriam funções associadas, como draw(), reportArea(), etc. também; se tentássemos importar diferentes funções com o mesmo nome para o mesmo arquivo de módulo de nível superior, acabaríamos com conflitos e erros.

- -

Felizmente, existem várias maneiras de contornar isso. Veremos isso nas próximas seções.

- -

Renomeando importações e exportações

- -

Dentro dos colchetes da instrução de importação e exportação, você pode usar a palavra-chave junto com um novo nome de recurso, para alterar o nome de identificação que será usado para um recurso dentro do módulo de nível superior.

- -

Por exemplo, os dois itens a seguir executariam o mesmo trabalho, embora de uma maneira ligeiramente diferente:

- -
// inside module.js
-export {
-  function1 as newFunctionName,
-  function2 as anotherNewFunctionName
-};
-
-// inside main.js
-import { newFunctionName, anotherNewFunctionName } from './modules/module.js';
- -
// inside module.js
-export { function1, function2 };
-
-// inside main.js
-import { function1 as newFunctionName,
-         function2 as anotherNewFunctionName } from './modules/module.js';
- -

Vejamos um exemplo real. Na nossa renaming diretório, você verá o mesmo sistema de módulos do exemplo anterior, exceto que adicionamos circle.js e triangle.js módulos para desenhar e relatar círculos e triângulos.

- -

Dentro de cada um desses módulos, temos recursos com os mesmos nomes sendo exportados e, portanto, cada um tem o mesmo export declaração na parte inferior:

- -
export { name, draw, reportArea, reportPerimeter };
- -

Ao importá-los para o main.js, se tentarmos usar

- -
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
-import { name, draw, reportArea, reportPerimeter } from './modules/circle.js';
-import { name, draw, reportArea, reportPerimeter } from './modules/triangle.js';
- -

O navegador geraria um erro como "SyntaxError: redeclaration of import name" (Firefox).

- -

Em vez disso, precisamos renomear as importações para que sejam únicas:

- -
import { name as squareName,
-         draw as drawSquare,
-         reportArea as reportSquareArea,
-         reportPerimeter as reportSquarePerimeter } from './modules/square.js';
-
-import { name as circleName,
-         draw as drawCircle,
-         reportArea as reportCircleArea,
-         reportPerimeter as reportCirclePerimeter } from './modules/circle.js';
-
-import { name as triangleName,
-        draw as drawTriangle,
-        reportArea as reportTriangleArea,
-        reportPerimeter as reportTrianglePerimeter } from './modules/triangle.js';
- -

Observe que você pode resolver o problema nos arquivos do módulo, e.g.

- -
// in square.js
-export { name as squareName,
-         draw as drawSquare,
-         reportArea as reportSquareArea,
-         reportPerimeter as reportSquarePerimeter };
- -
// in main.js
-import { squareName, drawSquare, reportSquareArea, reportSquarePerimeter } from './modules/square.js';
- -

E funcionaria da mesma forma. Qual o estilo que você usa depende de você, no entanto, sem dúvida faz mais sentido deixar o código do módulo em paz e fazer as alterações nas importações. Isso faz especialmente sentido quando você está importando de módulos de terceiros sobre os quais você não tem controle.

- -

24/5000

- -

Criando um objeto de módulo

- -

O método acima funciona bem, mas é um pouco confuso e longo. Uma solução ainda melhor é importar os recursos de cada módulo dentro de um objeto de módulo. O seguinte formulário de sintaxe faz isso:

- -
import * as Module from './modules/module.js';
- -

Isso captura todas as exportações disponíveis no module.js e as torna disponíveis como membros de um objeto Module, efetivamente dando o seu próprio namespace. Então, por exemplo:

- -
Module.function1()
-Module.function2()
-etc.
- -

Novamente, vejamos um exemplo real. Se você for ao nosso module-objects diretório, você verá o mesmo exemplo novamente, mas reescrito para aproveitar essa nova sintaxe. Nos módulos, as exportações são todas da seguinte forma simples:

- -
export { name, draw, reportArea, reportPerimeter };
- -

As importações, por outro lado, são assim:

- -
import * as Canvas from './modules/canvas.js';
-
-import * as Square from './modules/square.js';
-import * as Circle from './modules/circle.js';
-import * as Triangle from './modules/triangle.js';
- -

Em cada caso, agora você pode acessar as importações do módulo abaixo do nome do objeto especificado, por exemplo:

- -
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, 'blue');
-Square.reportArea(square1.length, reportList);
-Square.reportPerimeter(square1.length, reportList);
- -

Agora você pode escrever o código da mesma forma que antes (contanto que inclua os nomes dos objetos quando necessário) e as importações sejam muito mais limpas.

- -

Módulos e classes

- -

Como sugerimos anteriormente, você também pode exportar e importar classes; essa é outra opção para evitar conflitos no seu código e é especialmente útil se você já tiver o código do módulo gravado em um estilo orientado a objetos.

- -

Você pode ver um exemplo do nosso módulo de desenho de forma reescrito com as classes ES em nosso classes diretório. Como exemplo, o square.js O arquivo agora contém todas as suas funcionalidades em uma única classe:

- -
class Square {
-  constructor(ctx, listId, length, x, y, color) {
-    ...
-  }
-
-  draw() {
-    ...
-  }
-
-  ...
-}
- -

que exportamos então:

- -
export { Square };
- -

No main.js, nós o importamos assim:

- -
import { Square } from './modules/square.js';
- -

E então use a classe para desenhar nosso quadrado:

- -
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
-square1.draw();
-square1.reportArea();
-square1.reportPerimeter();
- -

Módulos de agregação

- -

Haverá momentos em que você desejará agregar módulos. Você pode ter vários níveis de dependências, nos quais deseja simplificar as coisas, combinando vários submódulos em um módulo pai. Isso é possível usando a sintaxe de exportação dos seguintes formulários no módulo pai:

- -
export * from 'x.js'
-export { name } from 'x.js'
- -

Por exemplo, veja nosso module-aggregation diretório. Neste exemplo (com base no exemplo de classes anteriores), temos um módulo extra chamado shapes.js, que agrega toda a funcionalidade de circle.js, square.js e triangle.js juntos. Também movemos nossos submódulos para dentro de um subdiretório dentro do diretório modules chamado shapes. Portanto, a estrutura do módulo neste exemplo é:

- -
modules/
-  canvas.js
-  shapes.js
-  shapes/
-    circle.js
-    square.js
-    triangle.js
- -

Em cada um dos submódulos, a exportação é da mesma forma, e.g.

- -
export { Square };
- -

Em seguida, vem a parte de agregação. Dentro de shapes.js, incluímos as seguintes linhas:

- -
export { Square } from './shapes/square.js';
-export { Triangle } from './shapes/triangle.js';
-export { Circle } from './shapes/circle.js';
- -

Eles capturam as exportações dos submódulos individuais e os disponibilizam efetivamente no módulo shapes.js.

- -
-

Nota: As exportações mencionadas no shapes.js são basicamente redirecionadas pelo arquivo e realmente não existem nele, portanto, você não poderá escrever nenhum código relacionado útil dentro do mesmo arquivo.

-
- -

Portanto, agora no arquivo main.js., podemos obter acesso às três classes de módulos substituindo

- -
import { Square } from './modules/square.js';
-import { Circle } from './modules/circle.js';
-import { Triangle } from './modules/triangle.js';
- -

com a seguinte linha única:

- -
import { Square, Circle, Triangle } from './modules/shapes.js';
- -

Carregamento dinâmico do módulo

- -

A parte mais recente da funcionalidade dos módulos JavaScript a estar disponível nos navegadores é o carregamento dinâmico de módulos. Isso permite que você carregue módulos dinamicamente somente quando eles forem necessários, em vez de precisar carregar tudo antecipadamente. Isso tem algumas vantagens óbvias de desempenho; vamos ler e ver como isso funciona.

- -

Essa nova funcionalidade permite que você ligue {{JSxRef("Statements/import", "import()", "#Dynamic_Imports")}} como uma função, passando o caminho para o módulo como um parâmetro. Retorna um{{JSxRef("Promise")}}, que cumpre com um objeto de módulo (consulte Creating a module object) dando acesso às exportações desse objeto, e.g.

- -
import('./modules/myModule.js')
-  .then((module) => {
-    // Do something with the module.
-  });
- -

Vejamos um exemplo. No dynamic-module-imports diretório, temos outro exemplo baseado em nosso exemplo de classes. Desta vez, no entanto, não estamos desenhando nada na tela quando o exemplo é carregado. Em vez disso, incluímos trêsbuttons — "Circle", "Square", e "Triangle" — que, quando pressionado, carrega dinamicamente o módulo necessário e, em seguida, usa-o para desenhar os shape.

- -

Neste exemplo, fizemos apenas alterações em nossa index.html e main.js arquivos - as exportações do módulo permanecem as mesmas de antes.

- -

No main.js, pegamos uma referência a cada botão usando umDocument.querySelector() chamada, por exemplo:

- -
let squareBtn = document.querySelector('.square');
- -

Em seguida, anexamos um ouvinte de evento a cada botão para que, quando pressionado, o módulo relevante seja carregado dinamicamente e usado para desenhar a forma(shape):

- -
squareBtn.addEventListener('click', () => {
-  import('./modules/square.js').then((Module) => {
-    let square1 = new Module.Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
-    square1.draw();
-    square1.reportArea();
-    square1.reportPerimeter();
-  })
-});
- -

Observe que, como o cumprimento da promessa retorna um objeto de módulo, a classe é então transformada em uma sub-característica do objeto, portanto, agora precisamos acessar o construtor com Module. anexado a ele, e.g. Module.Square( ... ).

- -

Solução de problemas

- -

Aqui estão algumas dicas que podem ajudá-lo se você estiver com problemas para fazer seus módulos funcionarem. Sinta-se livre para adicionar à lista se descobrir mais!

- - - -

Veja também

- - - -

{{Previous("Web/JavaScript/Guide/Meta_programming")}}

diff --git a/files/pt-br/web/javascript/guide/numbers_and_dates/index.html b/files/pt-br/web/javascript/guide/numbers_and_dates/index.html new file mode 100644 index 0000000000..8f08cb3619 --- /dev/null +++ b/files/pt-br/web/javascript/guide/numbers_and_dates/index.html @@ -0,0 +1,374 @@ +--- +title: Números e datas +slug: Web/JavaScript/Guide/Numeros_e_datas +translation_of: Web/JavaScript/Guide/Numbers_and_dates +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}
+ +

Este capítulo apresenta como utilizar números e datas em JavaScript.

+ +

Números

+ +

Em Javascript, todos os números são implementados em double-precision 64-bit binary format IEEE 754 (Por exemplo, um número entre -(253 -1) e 253 -1). Não havendo especificação de tipo Integer. Além de ser capaz de representar números de ponto flutuante, o tipo de número tem três valores simbólicos: +{{jsxref("Infinity")}}, -{{jsxref("Infinity")}}, and {{jsxref("NaN")}} (not-a-number).  Veja também Estruturas e Tipos de Dados em Javascript em contexto com outros tipos primitivos em JavaScript.

+ +

Você pode usar quatro tipos de números literais: decimal, binário, octal, e hexadecimal.

+ +

Números Decimais

+ +
1234567890
+42
+
+// Cuidado quando usar zeros à esquerda:
+
+0888 // 888 interpretado como decimal
+0777 // interpretado como octal  em modo no-strict (511 em decimal)
+
+ +

Note que literais decimais podem começar com zero (0)  seguido por outro digito decimal, porém se o próximo dígito depois do primeiro zero for menor do que 8, o número será analisado como um número octal.

+ +

Números Binários

+ +

A sintaxe para números Binários, usa um zero à esquerda seguido de uma letra minúscula ou maiúscula "B" (0b or 0B). Se os dígitos depois de 0b não forem 0 ou 1, a seguinte exceção SyntaxError é lançada: "Missing binary digits after 0b".

+ +
var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
+var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
+var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607
+ +

Números octais

+ +

A sintaxe dos números octais usa um zero na frente. Se os dígitos depois do 0 estiverem fora do alcance 0 a 7, o número será interpretado como um número decimal.

+ +
var n = 0755; // 493
+var m = 0644; // 420
+
+ +

Modo estrito no ECMAScript 5 proíbe a sintaxe octal. A sintaxe Octal não é parte do ECMAScript 5, mas é suportada por todos os navegadores prefixando o número octal com zero: 0644 === 420 e "\045" === "%". Em ECMAScript 6 números Octais são suportados prefixando o número com "0o" isto é.

+ +
var a = 0o10; // ES6: Octal
+
+ +

Numeros hexadecimais

+ +

A sintaxe numérica Hexadecimal usa um 0 na frente seguido por uma letra "X" maiúscula ou minúscula (0x ou 0X). Se os dígidos depois do 0x estiverem fora do alcance (0123456789ABCDF), o seguinte erro de sintaxe (SyntaxError) ocorrerá: "Identifier starts immediately after numeric literal" (O identificador começa imediatamente depois do literal numérico).

+ +
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
+0x123456789ABCDEF   // 81985529216486900
+0XA                 // 10
+
+ +

Exponenciação

+ +
1E3   // 1000
+2e6   // 2000000
+0.1e2 // 10
+ +

Objeto Number

+ +

Um objeto built-in {{jsxref("Number")}} tem propriedades para constantes numéricas, tais como valor máximo, não número e infinito. Você não pode alterar os valores dessas propriedades e elas são usadas assim:

+ +
var maiorNum = Number.MAX_VALUE; //Valor máximo
+var menorNum = Number.MIN_VALUE; //Valor mínimo
+var infiniteNum = Number.POSITIVE_INFINITY; //Infinito positivo
+var negInfiniteNum = Number.NEGATIVE_INFINITY; //Infinito negativo
+var notANum = Number.NaN; //Não é numeral
+
+ +

Você sempre se refere a uma propriedade do objeto predefinido Number como mostrado acima, e não como uma propriedade de um objeto Number que você mesmo criou.

+ +

A tabela à seguir sumariza as propriedades do objeto Number.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Propriedades de Number
PropriedadeDescrição
{{jsxref("Number.MAX_VALUE")}}O maior número representável.
{{jsxref("Number.MIN_VALUE")}}O menor número representável.
{{jsxref("Number.NaN")}}Valor "not a number" especial
{{jsxref("Number.NEGATIVE_INFINITY")}}Valor especial infinito negativo; retornado em overflow
{{jsxref("Number.POSITIVE_INFINITY")}}Valor especial infinito positivo; retornado em overflow
{{jsxref("Number.EPSILON")}}Diferença entre um e o menor valor maior do que um que pode ser representado como um {{jsxref("Number")}}.
{{jsxref("Number.MIN_SAFE_INTEGER")}}Mínimo safe integer em JavaScript.
{{jsxref("Number.MAX_SAFE_INTEGER")}}Máximo safe integer em JavaScript.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Métodos de Number
MétodoDescrição
{{jsxref("Number.parseFloat()")}}Analisa um argumento string e retorna um número float.
+ O mesmo que a função global {{jsxref("parseFloat", "parseFloat()")}}.
{{jsxref("Number.parseInt()")}}Analisa um argumento string e retorna um inteiro da raiz ou base especificada.
+ O mesmo que a função global{{jsxref("parseInt", "parseInt()")}}.
{{jsxref("Number.isFinite()")}}Determina se o valor passado é um número finito.
{{jsxref("Number.isInteger()")}}Determina se o valor passado é um inteiro.
{{jsxref("Number.isNaN()")}}Determina se o valor passado é {{jsxref("Global_Objects/NaN", "NaN")}}. A versão mais robusta da original {{jsxref("Global_Objects/isNaN", "isNaN()")}}.
{{jsxref("Number.isSafeInteger()")}}Determina se o valor passado é um safe integer.
+ +

O protótipo Number provê métodos para resgatar informações de objetos Number em vários formatos. A tabela a seguir sumariza os métodos de Number.prototype.

+ + + + + + + + + + + + + + + + + + + + + + + +
Métodos de Number.prototype
MétodoDescrição
{{jsxref("Number.toExponential", "toExponential()")}}Retorna uma string representando o número em uma notação exponencial.
{{jsxref("Number.toFixed", "toFixed()")}}Retorna uma string representando o número em notação com ponto-fíxo.
{{jsxref("Number.toPrecision", "toPrecision()")}}Retorna uma string representando o número em uma precisão especificada na notação de ponto-fíxo.
+ +

Objeto Math

+ +

O objeto {{jsxref("Math")}} tem propriedades e métodos para constantes matemáticas e funções. Por exemplo, o PI do objeto Math tem o valor de pi (3,141...), que você usaria em uma aplicação como

+ +
Math.PI
+
+ +

Similarmente, funções matemáticas padrão são métodos do Math. Isto inclui funções trigonométricas, logarítmicas, exponenciais, e outras funções. Por exemplo, se você quiser usar a função trigonométrica seno, basta escrever

+ +
Math.sin(1.56)
+
+ +

Note que todos os métodos trigonométricos pegam argumentos em radianos.

+ +

A tabela a seguir sumariza os métodos do objeto Math.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Métodos de Math
MétodoDescrição
{{jsxref("Math.abs", "abs()")}}Valor absoluto
{{jsxref("Math.sin", "sin()")}}, {{jsxref("Math.cos", "cos()")}}, {{jsxref("Math.tan", "tan()")}}Funções trigonométricas padrão; Argumentos em radianos
{{jsxref("Math.asin", "asin()")}}, {{jsxref("Math.acos", "acos()")}}, {{jsxref("Math.atan", "atan()")}}, {{jsxref("Math.atan2", "atan2()")}}Funções trigonométricas inversas; retorna valores em radianos
{{jsxref("Math.sinh", "sinh()")}}, {{jsxref("Math.cosh", "cosh()")}}, {{jsxref("Math.tanh", "tanh()")}}Funções trigonométricas hiperbólicas; retorna valores em radianos.
{{jsxref("Math.asinh", "asinh()")}}, {{jsxref("Math.acosh", "acosh()")}}, {{jsxref("Math.atanh", "atanh()")}}Funções trigonométricas hiperbólicas inversas; retorna valores em radianos.
+

{{jsxref("Math.pow", "pow()")}}, {{jsxref("Math.exp", "exp()")}}, {{jsxref("Math.expm1", "expm1()")}}, {{jsxref("Math.log10", "log10()")}}, {{jsxref("Math.log1p", "log1p()")}}, {{jsxref("Math.log2", "log2()")}}

+
Funções exponenciais e logarítmicas.
{{jsxref("Math.floor", "floor()")}}, {{jsxref("Math.ceil", "ceil()")}}Retorna o maior/menor inteiro que é menor/maior inteiro que ou igual ao argumento.
{{jsxref("Math.min", "min()")}}, {{jsxref("Math.max", "max()")}}Retorna menor ou maior (respectivamente) de uma lista separada por vírgula de argumentos numéricos
{{jsxref("Math.random", "random()")}}Retorna um número aleatório entre 0 e 1.
{{jsxref("Math.round", "round()")}}, {{jsxref("Math.fround", "fround()")}}, {{jsxref("Math.trunc", "trunc()")}},Funções de arredondamento e truncamento.
{{jsxref("Math.sqrt", "sqrt()")}}, {{jsxref("Math.cbrt", "cbrt()")}}, {{jsxref("Math.hypot", "hypot()")}}Raiz quadrada, raiz cúbica, raiz quadrada da soma de argumentos ao quadrado.
{{jsxref("Math.sign", "sign()")}}O sinal de um número, indicando se o número é positivo, negativo ou zero.
{{jsxref("Math.clz32", "clz32()")}},
+ {{jsxref("Math.imul", "imul()")}}
Número de zeros à esquerda na representação binária de 32-bits.
+ The result of the C-like 32-bit multiplication of the two arguments.
+ +

Diferentemente de muitos outros objetos, você nunca cria um objeto Math por conta própria. Você sempre deve utilizar o objeto Math nativo.

+ +

Objeto Date

+ +

JavaScript não possui dados do tipo data. No entanto, você pode usar o objeto {{jsxref("Date")}} e seus métodos para trabalhar com datas e horas nas suas aplicações. O objeto Date tem um grande número de métodos para setar, recuperar e manipular datas. Ele não tem nenhuma propriedade.

+ +

JavaScript manipula datas de maneira semelhante ao Java. As duas linguagens tem muitos dos mesmos métodos para lidar com datas e ambas armazenam datas como números em milisegundos, desde 1 de janeiro de 1970, às 00:00:00 ( January 1, 1970, 00:00:00).

+ +

A abrangência do objeto Date é de -100,000,000 dias até 100,000,000 dias relativos a 01 de janeiro de 1970 UTC.

+ +

Para criar um objeto Date:

+ +
var dateObjectName = new Date([parameters]);
+
+ +

onde dateObjectName é o nome do objeto Date que está sendo criado; ele pode ser um novo objeto ou uma propriedade de um objeto existente.

+ +

A chamada de Date sem a palavra reservada new, simplesmente converte a data para uma representação dela como string.

+ +

Os parâmetros do código acima podem ser qualquer um a seguir:

+ + + +

Métodos do objeto Date

+ +

Os métodos do objeto Date para manipular data e hora pertencem às seguintes categorias:

+ + + +

Com os métods "get" e "set", você pode recuperar e setar segundos, minutos, horas, dia e mês, dia da semana, meses e anos, separadamente. Existe um método getDay que retorna o dia da semana, mas não existe um método setDay correspondente, porque o dia da semana é setado automaticamente. Estes métodos utilizam números inteiros para representar estes valores da seguinte maneira:

+ + + +

Por exemplo, suponha que você queira definir a seguinite data:

+ +
var Xmas95 = new Date("December 25, 1995");
+
+ +

Então Xmas95.getMonth() retorna 11 e Xmas95.getFullYear() retorna 1995.

+ +

Os métodos getTime e setTime são úteis para comparar datas. O método getTime retorna o número dos milisegundos desde 1 de janeiro de 1970, às 00:00:00 para um objeto Date.

+ +

Por exemplo, o código a seguir mostra os números dos dias que ainda faltam do ano vigente:

+ +
var hoje = new Date();
+var fimAno = new Date(1995, 11, 31, 23, 59, 59, 999); // Seta dia e mês
+fimAno.setFullYear(hoje.getFullYear()); // Seta o ano para esse ano
+var msPorDia = 24 * 60 * 60 * 1000; // Quantidade de milisegundos por dia
+var diasRestantes = (fimAno.getTime() - hoje.getTime()) / msPorDia;
+var diasRestantes = Math.round(diasRestantes); //retorna os dias restantes no ano
+
+ +

Este exemplo cria um objeto Date chamado hoje que contém a data de hoje. Ele, então, cria o objeto Date chamado fimAno e seta o ano para o ano vigente. Então, usando o número de milisegundos por dia, ele computa o número de dias entre hoje e fimAno, usando getTime e arredondando os números de dias.

+ +

O método parse é útil para associar valores de strings de data para objetos Date existentes. Por exemplo, o código a seguir usa parse e setTime para associar um valor de data ao objeto IPOdate:

+ +
var IPOdate = new Date();
+IPOdate.setTime(Date.parse("Aug 9, 1995"));
+
+ +

No exemplo a seguir, a função  JSClock() retorna o tempo no formato de um relógio digital.

+ +
function JSClock() {
+  var tempo = new Date();
+  var hora = tempo.getHours();
+  var minuto = tempo.getMinutes();
+  var segundo = tempo.getSeconds();
+  var temp = "" + ((hora > 12) ? hora - 12 : hora);
+  if (hora == 0)
+    temp = "12";
+  temp += ((minuto < 10) ? ":0" : ":") + minuto;
+  temp += ((segundo < 10) ? ":0" : ":") + segundo;
+  temp += (hora >= 12) ? " P.M." : " A.M.";
+  return temp;
+}
+
+ +

A função JSClock primeiro cria um objeto new Date chamado tempo; já que nenhum argumento é passado, tempo é criado com data e hora atuais. Ela então chama os métodos getHours, getMinutes e getSeconds e associa o valor à hora, minuto e segundo atuais à hora, minuto e segundo.

+ +

As próximas quatro declarações constroem uma string baseada em time. A primeira declaração cria uma variável temp, associando um valor utilizando uma expressão condicional; se hora é maior que 12, (hora - 12), senão simplesmente hora, a não ser que hora seja 0 que, nesse caso, será 12.

+ +

A próxima declaração anexa um valor minuto a temp. Se o valor de minuto for menos que 10, a expressão condicional acrescenta uma string com um 0 na frente; senão ela acrescenta uma string com dois pontos. Então a declaração anexa um valor segundo a temp do mesmo jeito.

+ +

Finalmente, a expressão condicional anexa "P.M." a temp se hora for 12 ou maior; senão ela anexa "A.M." a temp.

+ +

{{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}

diff --git a/files/pt-br/web/javascript/guide/numeros_e_datas/index.html b/files/pt-br/web/javascript/guide/numeros_e_datas/index.html deleted file mode 100644 index 8f08cb3619..0000000000 --- a/files/pt-br/web/javascript/guide/numeros_e_datas/index.html +++ /dev/null @@ -1,374 +0,0 @@ ---- -title: Números e datas -slug: Web/JavaScript/Guide/Numeros_e_datas -translation_of: Web/JavaScript/Guide/Numbers_and_dates ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}
- -

Este capítulo apresenta como utilizar números e datas em JavaScript.

- -

Números

- -

Em Javascript, todos os números são implementados em double-precision 64-bit binary format IEEE 754 (Por exemplo, um número entre -(253 -1) e 253 -1). Não havendo especificação de tipo Integer. Além de ser capaz de representar números de ponto flutuante, o tipo de número tem três valores simbólicos: +{{jsxref("Infinity")}}, -{{jsxref("Infinity")}}, and {{jsxref("NaN")}} (not-a-number).  Veja também Estruturas e Tipos de Dados em Javascript em contexto com outros tipos primitivos em JavaScript.

- -

Você pode usar quatro tipos de números literais: decimal, binário, octal, e hexadecimal.

- -

Números Decimais

- -
1234567890
-42
-
-// Cuidado quando usar zeros à esquerda:
-
-0888 // 888 interpretado como decimal
-0777 // interpretado como octal  em modo no-strict (511 em decimal)
-
- -

Note que literais decimais podem começar com zero (0)  seguido por outro digito decimal, porém se o próximo dígito depois do primeiro zero for menor do que 8, o número será analisado como um número octal.

- -

Números Binários

- -

A sintaxe para números Binários, usa um zero à esquerda seguido de uma letra minúscula ou maiúscula "B" (0b or 0B). Se os dígitos depois de 0b não forem 0 ou 1, a seguinte exceção SyntaxError é lançada: "Missing binary digits after 0b".

- -
var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
-var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
-var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607
- -

Números octais

- -

A sintaxe dos números octais usa um zero na frente. Se os dígitos depois do 0 estiverem fora do alcance 0 a 7, o número será interpretado como um número decimal.

- -
var n = 0755; // 493
-var m = 0644; // 420
-
- -

Modo estrito no ECMAScript 5 proíbe a sintaxe octal. A sintaxe Octal não é parte do ECMAScript 5, mas é suportada por todos os navegadores prefixando o número octal com zero: 0644 === 420 e "\045" === "%". Em ECMAScript 6 números Octais são suportados prefixando o número com "0o" isto é.

- -
var a = 0o10; // ES6: Octal
-
- -

Numeros hexadecimais

- -

A sintaxe numérica Hexadecimal usa um 0 na frente seguido por uma letra "X" maiúscula ou minúscula (0x ou 0X). Se os dígidos depois do 0x estiverem fora do alcance (0123456789ABCDF), o seguinte erro de sintaxe (SyntaxError) ocorrerá: "Identifier starts immediately after numeric literal" (O identificador começa imediatamente depois do literal numérico).

- -
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
-0x123456789ABCDEF   // 81985529216486900
-0XA                 // 10
-
- -

Exponenciação

- -
1E3   // 1000
-2e6   // 2000000
-0.1e2 // 10
- -

Objeto Number

- -

Um objeto built-in {{jsxref("Number")}} tem propriedades para constantes numéricas, tais como valor máximo, não número e infinito. Você não pode alterar os valores dessas propriedades e elas são usadas assim:

- -
var maiorNum = Number.MAX_VALUE; //Valor máximo
-var menorNum = Number.MIN_VALUE; //Valor mínimo
-var infiniteNum = Number.POSITIVE_INFINITY; //Infinito positivo
-var negInfiniteNum = Number.NEGATIVE_INFINITY; //Infinito negativo
-var notANum = Number.NaN; //Não é numeral
-
- -

Você sempre se refere a uma propriedade do objeto predefinido Number como mostrado acima, e não como uma propriedade de um objeto Number que você mesmo criou.

- -

A tabela à seguir sumariza as propriedades do objeto Number.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Propriedades de Number
PropriedadeDescrição
{{jsxref("Number.MAX_VALUE")}}O maior número representável.
{{jsxref("Number.MIN_VALUE")}}O menor número representável.
{{jsxref("Number.NaN")}}Valor "not a number" especial
{{jsxref("Number.NEGATIVE_INFINITY")}}Valor especial infinito negativo; retornado em overflow
{{jsxref("Number.POSITIVE_INFINITY")}}Valor especial infinito positivo; retornado em overflow
{{jsxref("Number.EPSILON")}}Diferença entre um e o menor valor maior do que um que pode ser representado como um {{jsxref("Number")}}.
{{jsxref("Number.MIN_SAFE_INTEGER")}}Mínimo safe integer em JavaScript.
{{jsxref("Number.MAX_SAFE_INTEGER")}}Máximo safe integer em JavaScript.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Métodos de Number
MétodoDescrição
{{jsxref("Number.parseFloat()")}}Analisa um argumento string e retorna um número float.
- O mesmo que a função global {{jsxref("parseFloat", "parseFloat()")}}.
{{jsxref("Number.parseInt()")}}Analisa um argumento string e retorna um inteiro da raiz ou base especificada.
- O mesmo que a função global{{jsxref("parseInt", "parseInt()")}}.
{{jsxref("Number.isFinite()")}}Determina se o valor passado é um número finito.
{{jsxref("Number.isInteger()")}}Determina se o valor passado é um inteiro.
{{jsxref("Number.isNaN()")}}Determina se o valor passado é {{jsxref("Global_Objects/NaN", "NaN")}}. A versão mais robusta da original {{jsxref("Global_Objects/isNaN", "isNaN()")}}.
{{jsxref("Number.isSafeInteger()")}}Determina se o valor passado é um safe integer.
- -

O protótipo Number provê métodos para resgatar informações de objetos Number em vários formatos. A tabela a seguir sumariza os métodos de Number.prototype.

- - - - - - - - - - - - - - - - - - - - - - - -
Métodos de Number.prototype
MétodoDescrição
{{jsxref("Number.toExponential", "toExponential()")}}Retorna uma string representando o número em uma notação exponencial.
{{jsxref("Number.toFixed", "toFixed()")}}Retorna uma string representando o número em notação com ponto-fíxo.
{{jsxref("Number.toPrecision", "toPrecision()")}}Retorna uma string representando o número em uma precisão especificada na notação de ponto-fíxo.
- -

Objeto Math

- -

O objeto {{jsxref("Math")}} tem propriedades e métodos para constantes matemáticas e funções. Por exemplo, o PI do objeto Math tem o valor de pi (3,141...), que você usaria em uma aplicação como

- -
Math.PI
-
- -

Similarmente, funções matemáticas padrão são métodos do Math. Isto inclui funções trigonométricas, logarítmicas, exponenciais, e outras funções. Por exemplo, se você quiser usar a função trigonométrica seno, basta escrever

- -
Math.sin(1.56)
-
- -

Note que todos os métodos trigonométricos pegam argumentos em radianos.

- -

A tabela a seguir sumariza os métodos do objeto Math.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Métodos de Math
MétodoDescrição
{{jsxref("Math.abs", "abs()")}}Valor absoluto
{{jsxref("Math.sin", "sin()")}}, {{jsxref("Math.cos", "cos()")}}, {{jsxref("Math.tan", "tan()")}}Funções trigonométricas padrão; Argumentos em radianos
{{jsxref("Math.asin", "asin()")}}, {{jsxref("Math.acos", "acos()")}}, {{jsxref("Math.atan", "atan()")}}, {{jsxref("Math.atan2", "atan2()")}}Funções trigonométricas inversas; retorna valores em radianos
{{jsxref("Math.sinh", "sinh()")}}, {{jsxref("Math.cosh", "cosh()")}}, {{jsxref("Math.tanh", "tanh()")}}Funções trigonométricas hiperbólicas; retorna valores em radianos.
{{jsxref("Math.asinh", "asinh()")}}, {{jsxref("Math.acosh", "acosh()")}}, {{jsxref("Math.atanh", "atanh()")}}Funções trigonométricas hiperbólicas inversas; retorna valores em radianos.
-

{{jsxref("Math.pow", "pow()")}}, {{jsxref("Math.exp", "exp()")}}, {{jsxref("Math.expm1", "expm1()")}}, {{jsxref("Math.log10", "log10()")}}, {{jsxref("Math.log1p", "log1p()")}}, {{jsxref("Math.log2", "log2()")}}

-
Funções exponenciais e logarítmicas.
{{jsxref("Math.floor", "floor()")}}, {{jsxref("Math.ceil", "ceil()")}}Retorna o maior/menor inteiro que é menor/maior inteiro que ou igual ao argumento.
{{jsxref("Math.min", "min()")}}, {{jsxref("Math.max", "max()")}}Retorna menor ou maior (respectivamente) de uma lista separada por vírgula de argumentos numéricos
{{jsxref("Math.random", "random()")}}Retorna um número aleatório entre 0 e 1.
{{jsxref("Math.round", "round()")}}, {{jsxref("Math.fround", "fround()")}}, {{jsxref("Math.trunc", "trunc()")}},Funções de arredondamento e truncamento.
{{jsxref("Math.sqrt", "sqrt()")}}, {{jsxref("Math.cbrt", "cbrt()")}}, {{jsxref("Math.hypot", "hypot()")}}Raiz quadrada, raiz cúbica, raiz quadrada da soma de argumentos ao quadrado.
{{jsxref("Math.sign", "sign()")}}O sinal de um número, indicando se o número é positivo, negativo ou zero.
{{jsxref("Math.clz32", "clz32()")}},
- {{jsxref("Math.imul", "imul()")}}
Número de zeros à esquerda na representação binária de 32-bits.
- The result of the C-like 32-bit multiplication of the two arguments.
- -

Diferentemente de muitos outros objetos, você nunca cria um objeto Math por conta própria. Você sempre deve utilizar o objeto Math nativo.

- -

Objeto Date

- -

JavaScript não possui dados do tipo data. No entanto, você pode usar o objeto {{jsxref("Date")}} e seus métodos para trabalhar com datas e horas nas suas aplicações. O objeto Date tem um grande número de métodos para setar, recuperar e manipular datas. Ele não tem nenhuma propriedade.

- -

JavaScript manipula datas de maneira semelhante ao Java. As duas linguagens tem muitos dos mesmos métodos para lidar com datas e ambas armazenam datas como números em milisegundos, desde 1 de janeiro de 1970, às 00:00:00 ( January 1, 1970, 00:00:00).

- -

A abrangência do objeto Date é de -100,000,000 dias até 100,000,000 dias relativos a 01 de janeiro de 1970 UTC.

- -

Para criar um objeto Date:

- -
var dateObjectName = new Date([parameters]);
-
- -

onde dateObjectName é o nome do objeto Date que está sendo criado; ele pode ser um novo objeto ou uma propriedade de um objeto existente.

- -

A chamada de Date sem a palavra reservada new, simplesmente converte a data para uma representação dela como string.

- -

Os parâmetros do código acima podem ser qualquer um a seguir:

- - - -

Métodos do objeto Date

- -

Os métodos do objeto Date para manipular data e hora pertencem às seguintes categorias:

- - - -

Com os métods "get" e "set", você pode recuperar e setar segundos, minutos, horas, dia e mês, dia da semana, meses e anos, separadamente. Existe um método getDay que retorna o dia da semana, mas não existe um método setDay correspondente, porque o dia da semana é setado automaticamente. Estes métodos utilizam números inteiros para representar estes valores da seguinte maneira:

- - - -

Por exemplo, suponha que você queira definir a seguinite data:

- -
var Xmas95 = new Date("December 25, 1995");
-
- -

Então Xmas95.getMonth() retorna 11 e Xmas95.getFullYear() retorna 1995.

- -

Os métodos getTime e setTime são úteis para comparar datas. O método getTime retorna o número dos milisegundos desde 1 de janeiro de 1970, às 00:00:00 para um objeto Date.

- -

Por exemplo, o código a seguir mostra os números dos dias que ainda faltam do ano vigente:

- -
var hoje = new Date();
-var fimAno = new Date(1995, 11, 31, 23, 59, 59, 999); // Seta dia e mês
-fimAno.setFullYear(hoje.getFullYear()); // Seta o ano para esse ano
-var msPorDia = 24 * 60 * 60 * 1000; // Quantidade de milisegundos por dia
-var diasRestantes = (fimAno.getTime() - hoje.getTime()) / msPorDia;
-var diasRestantes = Math.round(diasRestantes); //retorna os dias restantes no ano
-
- -

Este exemplo cria um objeto Date chamado hoje que contém a data de hoje. Ele, então, cria o objeto Date chamado fimAno e seta o ano para o ano vigente. Então, usando o número de milisegundos por dia, ele computa o número de dias entre hoje e fimAno, usando getTime e arredondando os números de dias.

- -

O método parse é útil para associar valores de strings de data para objetos Date existentes. Por exemplo, o código a seguir usa parse e setTime para associar um valor de data ao objeto IPOdate:

- -
var IPOdate = new Date();
-IPOdate.setTime(Date.parse("Aug 9, 1995"));
-
- -

No exemplo a seguir, a função  JSClock() retorna o tempo no formato de um relógio digital.

- -
function JSClock() {
-  var tempo = new Date();
-  var hora = tempo.getHours();
-  var minuto = tempo.getMinutes();
-  var segundo = tempo.getSeconds();
-  var temp = "" + ((hora > 12) ? hora - 12 : hora);
-  if (hora == 0)
-    temp = "12";
-  temp += ((minuto < 10) ? ":0" : ":") + minuto;
-  temp += ((segundo < 10) ? ":0" : ":") + segundo;
-  temp += (hora >= 12) ? " P.M." : " A.M.";
-  return temp;
-}
-
- -

A função JSClock primeiro cria um objeto new Date chamado tempo; já que nenhum argumento é passado, tempo é criado com data e hora atuais. Ela então chama os métodos getHours, getMinutes e getSeconds e associa o valor à hora, minuto e segundo atuais à hora, minuto e segundo.

- -

As próximas quatro declarações constroem uma string baseada em time. A primeira declaração cria uma variável temp, associando um valor utilizando uma expressão condicional; se hora é maior que 12, (hora - 12), senão simplesmente hora, a não ser que hora seja 0 que, nesse caso, será 12.

- -

A próxima declaração anexa um valor minuto a temp. Se o valor de minuto for menos que 10, a expressão condicional acrescenta uma string com um 0 na frente; senão ela acrescenta uma string com dois pontos. Então a declaração anexa um valor segundo a temp do mesmo jeito.

- -

Finalmente, a expressão condicional anexa "P.M." a temp se hora for 12 ou maior; senão ela anexa "A.M." a temp.

- -

{{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}

diff --git a/files/pt-br/web/javascript/guide/sintaxe_e_tipos/index.html b/files/pt-br/web/javascript/guide/sintaxe_e_tipos/index.html deleted file mode 100644 index 953a9543de..0000000000 --- a/files/pt-br/web/javascript/guide/sintaxe_e_tipos/index.html +++ /dev/null @@ -1,583 +0,0 @@ ---- -title: Sintaxe e tipos -slug: Web/JavaScript/Guide/Sintaxe_e_tipos ---- -
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}
- -

Este capítulo trata sobre a sintaxe básica do JavaScript, declarações de variáveis, tipos de dados e literais.

- -

Sintaxe básica

- -

JavaScript pega emprestado a maior parte de sua sintaxe do Java, mas também é influenciado por Awk, Perl e Python.

- -

JavaScript é case-sensitive e usa o conjunto de caracteres Unicode.

- -

No JavaScript, instruções são chamadas de {{Glossary("Statement", "declarações")}} e são separadas por um ponto e vírgula (;). Espaços, tabulação e uma nova linha são chamados de espaços em branco. O código fonte dos scripts em JavaScript são lidos da esquerda para a direita e são convertidos em uma sequência de elementos de entrada como simbolos, caracteres de controle, terminadores de linha, comentários ou espaço em branco. ECMAScript também define determinadas palavras-chave e literais, e tem regras para inserção automática de ponto e vírgula (ASI) para terminar as declarações. No entanto, recomenda-se sempre adicionar ponto e vírgula no final de suas declarações; isso evitará alguns imprevistos. Para obter mais informações, consulte a referência detalhada sobre a gramática léxica do JavaScript.

- -

Comentários

- -

A sintaxe dos comentários em JavaScript é semelhante como em C++ e em muitas outras linguagens:

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

Declarações

- -

Existem três tipos de declarações em JavaScript.

- -
-
{{jsxref("Statements/var", "var")}}
-
Declara uma variável, opcionalmente, inicializando-a com um valor.
-
{{experimental_inline}} {{jsxref("Statements/let", "let")}}
-
Declara uma variável local de escopo do bloco, opcionalmente, inicializando-a com um valor.
-
{{experimental_inline}} {{jsxref("Statements/const", "const")}}
-
Declara uma constante apenas de leitura.
-
- -

Variáveis

- -

Você usa variáveis como nomes simbólicos para os valores em sua aplicação. O nome das variáveis, chamados de {{Glossary("Identifier", "identificadores")}}, obedecem determinadas regras.

- -

Um identificador JavaScript deve começar com uma letra, underline (_), ou cifrão ($); os caracteres subsequentes podem também ser números (0-9). Devido JavaScript ser case-sensitive, letras incluem caracteres de "A" a "Z" (maiúsculos) e caracteres de "a" a "z" (minúsculos).

- -

Você pode usar a ISO 8859-1 ou caracteres Unicode tal como os identificadores å e ü. Você pode também usar as sequências de escape Unicode como caracteres e identificadores.

- -

Alguns exemplos de nomes legais são Numeros_visitas, temp99, e _nome.

- -

Declarando variáveis

- -

Você pode declarar uma variável de três formas:

- - - -

Classificando variáveis

- -

Uma variável declarada usando a declaração var ou let sem especificar o valor inicial tem o valor  {{jsxref("undefined")}}.

- -

Uma tentativa de acessar uma variável não declarada resultará no lançamento de uma exceção {{jsxref("ReferenceError")}}:

- -
var a;
-console.log("O valor de a é " + a); // saída "O valor de a é undefined"
-console.log("O valor de b é " + b); // throws ReferenceError exception
-
- -

Você pode usar undefined para determinar se uma variável tem um valor. No código a seguir, não é atribuído um valor de entrada na variável e a declaração if será avaliada como verdadeira (true).

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

O valor undefined se comporta como falso (false), quando usado em um contexto booleano. Por exemplo, o código a seguir executa a função myFunction devido o elemento myArray ser undefined:

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

O valor undefined converte-se para NaN quando usado no contexto numérico.

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

Quando você avalia uma variável nula, o valor nulo se comporta como 0 em contextos numéricos e como falso em contextos booleanos. Por exemplo:

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

Escopo de variável

- -

Quando você declara uma váriavel fora de qualquer função, ela é chamada de variável global, porque está disponível para qualquer outro código no documento atual. Quando você declara uma variável dentro de uma função, é chamada de variável local,  pois ela está disponível somente dentro dessa função.

- -

JavaScript antes do ECMAScript 6 não possuía escopo de declaração de bloco; pelo contrário, uma variável declarada dentro de um bloco de uma função é uma variável local (ou contexto global) do bloco que está inserido a função. Por exemplo o código a seguir exibirá 5, porque o escopo de x está na função (ou contexto global) no qual x é declarado, não o bloco, que neste caso é a declaração if

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

Esse comportamento é alterado, quando usado a declaração let introduzida pelo ECMAScript 6.

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

Hoisting

- -

Outra coisa incomum sobre variáveis em JavaScript é que você pode utilizar a variável e declará-la depois, sem obter uma exceção. Este conceito é conhecido como hoisting; variáveis em JavaScript são num sentido "hoisted" ou lançada para o topo da função ou declaração. No entanto, as variáveis que são "hoisted" retornarão um valor undefined. Então, mesmo se você usar ou referir a variável e depois declará-la e inicializá-la, ela ainda retornará undefined.

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

Os exemplos acima serão interpretados como:

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

Devido o hoisting, todas as declarações var em uma função devem ser colocadas no início da função. Essa recomendação de prática deixa o código mais legível.

- -

Variáveis Globais

- -

Variáveis globais são propriedades do objeto global. Em páginas web o objeto global é a {{domxref("window")}}, assim você pode configurar e acessar variáveis globais utilizando a sintaxe window.variavel. 

- -

Consequentemente, você pode acessar variáveis globais declaradas em uma janela ou frame ou frame de outra janela. Por exemplo, se uma variável chamada phoneNumber é declarada em um documento, você pode consultar esta variável de um frame como parent.phoneNumber.

- -

Constantes

- -

Você pode criar uma constante apenas de leitura por meio da palavra-chave {{jsxref("Statements/const", "const")}}. A sintaxe de um identificador de uma constante é semelhante ao identificador de uma variável: deve começar com uma letra, underline ou cifrão e pode conter caracteres alfabético, numérico ou underline.

- -
const prefix = '212';
-
- -

Uma constante não pode alterar seu valor por meio de uma atribuição ou ao ser declarada novamente enquanto o script é executado. Deve ser inicializada com um valor.

- -

As regras de escopo para as constantes são as mesmas para as váriaveis let de escopo de bloco. Se a palavra-chave const for omitida, o identificado é adotado para representar uma variável.

- -

Você não pode declarar uma constante com o mesmo nome de uma função ou variável que estão no mesmo escopo. Por exemplo: 

- -
// Isto irá causar um  erro
-function f() {};
-const f = 5;
-
-// Isto também irá causar um erro.
-function f() {
-  const g = 5;
-  var g;
-
-  //declarações
-}
-
- -

Estrutura de dados e tipos

- -

Tipos de dados

- -

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

- - - -

Embora esses tipos de dados sejam uma quantidade relativamente pequena, eles permitem realizar funções úteis em suas aplicações.  {{jsxref("Object", "Objetos")}} e {{jsxref("Function", "funçõess")}} são outros elementos fundamentais na linguagem. Você pode pensar em objetos como recipientes para os valores, e funções como métodos que suas aplicações podem executar.

- -

Conversão de tipos de dados

- -

JavaScript é uma linguagem dinamicamente tipada. Isso significa que você não precisa especificar o tipo de dado de uma variável quando declará-la, e tipos de dados são convertidos automaticamente conforme a necessidade durante a execução do script. Então, por exemplo, você pode definir uma variável da seguinte forma:

- -
var answer = 42;
-
- -

E depois, você pode atribuir uma string para a mesma variável, por exemplo:

- -
answer = "Obrigado pelos peixes...";
-
- -

Devido JavaScript ser dinamicamente tipado, essa declaração não gera uma mensagem de erro.

- -

Em expressões envolvendo valores numérico e string com o operador +, JavaScript converte valores numérico para strings. Por exemplo, considere a seguinte declaração:

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

Nas declarações envolvendo outros operadores,  JavaScript não converte valores numérico para strings. Por exemplo:

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

Convertendo strings para números

- -

No caso de um valor que representa um número está armazenado na memória como uma string, existem métodos para a conversão.

- - - -

parseInt irá retornar apenas números inteiros, então seu uso é restrito para a casa dos decimais. Além disso, é uma boa prática ao usar parseInt incluir o parâmetro da base. O parâmetro da base é usado para especificar qual sistema númerico deve ser usado.

- -

Uma método alternativo de conversão de um número em forma de string é com o operador + (operador soma):

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

Literais

- -

Você usa literais para representar valores em JavaScript. Estes são valores fixados, não variáveis, que você literalmente insere em seu script. Esta seção descreve os seguintes tipos literais:

- - - -

Array literal

- -

Um literal de array é uma lista de zero ou mais expressões, onde cada uma delas representam um elemento do array, inseridas entre colchetes ([]). Quando você cria um array usando um array literal, ele é inicializado  com os valores especificados como seus elementos, e seu comprimento é definido com o  número de elementos especificados.

- -

O exemplo a seguir cria um array coffees com três elementos e um comprimento de três:

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

Nota : Um array literal é um tipo de inicializador de objetos. Veja Usando inicializadores de Objetos.

-
- -

Se um array é criado usando um literal no topo do script, JavaScript interpreta o array cada vez que avalia a expressão que contêm o array literal. Além disso, um literal usado em uma função é criado cada vez que a função é chamada.

- -

Array literal são também um array de objetos. Veja  {{jsxref("Array")}} e Coleções indexadas para detalhes sobre array de objetos.

- -

Vírgulas extras em array literal

- -

Você não precisa especificar todos os elementos em um array literal. Se você colocar duas vírgulas em uma linha, o array é criado com undefined para os elementos não especificados. O exemplo a seguir cria um array chamado fish:

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

Esse array tem dois elementos com valores e um elemento vazio (fish[0] é "Lion", fish[1] é undefined, e fish[2] é "Angel" ).

- -

Se você incluir uma vírgula à direita no final da lista dos elementos, a vírgula é ignorada. No exemplo a seguir, o comprimento do array é três. Não há nenhum myList[3]. Todas as outras vírgulas na lista indicam um novo elemento.

- -
-

Nota : Vírgulas à direita podem criar erros em algumas versões de navegadores web antigos, é recomendável removê-las.

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

No exemplo a seguir, o comprimento do array é quatro, e myList[0] e myList[2] são undefined.

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

No exemplo a seguir, o comprimento do array é quatro, e myList[1] e myList[3] são undefined. Apenas a última vírgula é ignorada.

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

Entender o comportamento de vírgulas extras é importante para a compreensão da linguagem JavaScript, no entanto, quando você escrever seu próprio código: declarar explicitamente os elementos em falta como undefined vai aumentar a clareza do código, e consequentemente na sua manutenção.

- -

Literais Boolean

- -

O tipo Boolean tem dois valores literal: true e false.

- -

Não confunda os valores primitivos Boolean true e false com os valores true e false do objeto Boolean. O objeto Boolean é um invólucro em torno do tipo de dado primitivo. Veja {{jsxref("Boolean")}} para mais informação.

- -

Inteiros

- -

Inteiros podem sem expressos em decimal (base 10), hexadecimal (base 16), octal (base 8) e binário (base 2).

- - - -

Alguns exemplos de inteiros literal são:

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

Para maiores informações, veja Literais numérico na referência Léxica.

- -

Literais de ponto flutuante

- -

Um literal de ponto flutuante pode ter as seguintes partes:

- - - -

O expoente é um "e" ou "E" seguido por um inteiro, que pode ter sinal (precedido por "+" ou "-"). Um literal de ponto flutuante  deve ter no mínimo um dígito e um ponto decimal ou "e" (ou "E").

- -

Mais sucintamente, a sintaxe é:

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

Por exemplo:

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

Objeto literal

- -

Um objeto literal é uma lista de zero ou mais pares de nomes de propriedades e valores associados de de um objeto, colocado entre chaves ({}). Você não deve usar um objeto literal no início de uma declaração. Isso levará a um erro ou não se comportará conforme o esperado, porque o { será interpretado como início de um bloco.

- -

Segue um exemplo de um objeto literal. O primeiro elemento do objeto car define uma propriedade, myCar, e atribui para ele uma nova string, "Saturn"; o segundo elemento, a propriedade getCar, é imediatamente atribuído o resultado de chamar uma função (carTypes("Honda")); o terceiro elemento, a propriedade especial, usa uma variável existente (sales).

- -
var sales = "Toyota";
-
-function carTypes(name) {
-  if (name == "Honda") {
-    return name;
-  } else {
-    return "Sorry, we don't sell " + name + ".";
-  }
-}
-
-var car = { myCar: "Saturn", getCar: carTypes("Honda"), special: sales };
-
-console.log(car.myCar);   // Saturn
-console.log(car.getCar);  // Honda
-console.log(car.special); // Toyota
-
- -

Além disso, você pode usar um literal numérico ou string para o nome de uma propriedade ou aninhar um objeto dentro do outro. O exemplo a seguir usar essas opções.

- -
var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };
-
-console.log(car.manyCars.b); // Jeep
-console.log(car[7]); // Mazda
-
- -

Nomes de propriedades de objeto podem ser qualquer string, incluindo uma string vazia. Caso o nome da propriedade não seja um {{Glossary("Identifier","identificador")}} JavaScript ou número, ele deve ser colocado entre aspas. Nomes de propriedades que não possuem identificadores válido, também não podem ser acessadas pela propriedade de ponto (.), mas podem ser acessadas e definidas com a notação do tipo array ("[]").

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

Observe:

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

String Literal

- -

Uma string literal são zero ou mais caracteres dispostos em aspas duplas (") ou aspas simples ('). Uma sequência de caracteres deve ser delimitada por aspas do mesmo tipo; ou seja,  as duas aspas simples ou ambas aspas duplas. A seguir um exemplo de strings literais.

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

Você pode chamar qualquer um dos métodos do objeto string em uma string literal - JavaScript automaticamente converte a string literal para um objeto string temporário, chama o método, em seguida, descarta o objeto string temporário. Você também pode usar a propriedade String.length com uma string literal:

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

Você deve usar string literal, a não ser que você precise usar um objeto string. Veja {{jsxref("String")}} para detalhes sobre objetos de strings.

- -

Uso de caracteres especiais em string

- -

Além dos caracteres comuns, você também pode incluir caracteres especiais em strings, como mostrado no exemplo a seguir.

- -
"uma linha \n outra linha"
-
- -

A tabela a seguir lista os caracteres especiais que podem ser usados em strings no JavaScript.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tabela: Caracteres especiais no JavaScript
CaracterDescrição
\0Byte nulo
\bBackspace
\fAlimentador de formulário
\nNova linha
\rRetorno do carro
\tTabulação
\vTabulação vertical
\'Apóstrofo ou aspas simples
\"Aspas dupla
\\Caractere de barra invertida
\XXX -

Caractere com a codificação Latin-1 especificada por três dígitos octal XXX entre 0 e 377. Por exemplo, \251 é sequência octal para o símbolo de direitos autorais.

-
\xXX -

Caractere com a codificação Latin-1 especificada por dois dígitos hexadecimal XX entre 00 e FF. Por exemplo, \xA9 é a sequência hexadecimal para o símbolo de direitos autorais.

-
\uXXXX -

Caractere Unicode especificado por quatro dígitos hexadecimal XXXX. Por exemplo, \u00A9 é a sequência Unicode para o símbolo de direitos autorais. Veja sequências de escape Unicode.

-
- -

Caracteres de escape

- -

Para caracteres não listados na tabela, se precedidos de barra invertida ela é ignorada, seu uso está absoleto e deve ser ignorado.

- -

Você pode inserir uma aspa dentro de uma string precendendo-a com uma barra invertida. Isso  é conhecido como escaping das aspas. Por exemplo:

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

O resultado disso seria:

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

Para incluir uma barra invertida dentro de uma string, você deve escapar o caractere de barra invertida. Por exemplo, para atribuir o caminho do arquivo c:\temp para uma string, utilize o seguinte:

- -
var home = "c:\\temp";
-
- -

Você também pode escapar quebras de linhas, precedendo-as com barra invertida. A barra invertida e a quebra de linha são ambas removidas da string.

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

Embora JavaScript não tenha sintaxe "heredoc", você pode adicionar uma quebra de linha e um escape de quebra de linha no final de cada linha:

- -
var poem =
-"Rosas são vermelhas,\n\
-Violetas são azul.\n\
-Eu sou esquizofrênico,\n\
-e é isso que sou."
-
- -

Mais informação

- -

Este capítulo focou na sintaxe básica das declarações e tipos. Para saber mais sobre a linguagem JavaScript, veja também os seguintes capítulos deste guia:

- - - -

No próximo capítulo, veremos a construção de controle de fluxos e manipulação de erro.

- -

{{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}

diff --git a/files/pt-br/web/javascript/guide/text_formatting/index.html b/files/pt-br/web/javascript/guide/text_formatting/index.html new file mode 100644 index 0000000000..1b4bb50772 --- /dev/null +++ b/files/pt-br/web/javascript/guide/text_formatting/index.html @@ -0,0 +1,250 @@ +--- +title: Formatando texto +slug: Web/JavaScript/Guide/Formatando_texto +tags: + - Guía + - JavaScript +translation_of: Web/JavaScript/Guide/Text_formatting +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
+ +

Esse capítulo introduz como trabalhar com strings e texto em JavaScript.

+ +

Strings

+ +

O tipo {{Glossary("String")}} do JavaScript é usado para representar informações de texto. É um conjunto de "elementos" composto por valores inteiros de 16-bits sem sinal. Cada elemento dentro da String ocupa uma posição dentro dessa String. O primeiro elemento está no índice 0, o próximo no índice 1, e assim sucessivamente. O tamanho de uma String é a quantidade de elementos que ela possui. Você pode criar strings usando strings literais ou objetos string.

+ +

Strings literais

+ +

Você pode criar strings usando aspas simples ou aspas duplas:

+ +
'foo'
+"bar"
+ +

Strings mais avançadas podem ser criadas usando sequências de escape:

+ +

Sequências de escape hexadecimais

+ +

O número depois de \x é interpretado como um número hexadecimal.

+ +
'\xA9' // "©"
+
+ +

Sequências de escape unicode

+ +

As sequências de escape unicode requerem no mínimo quatro caracteres depois do \u.

+ +
'\u00A9' // "©"
+ +

Sequências de escape Unicode code point

+ +

É novo no ECMAScript 6. Com essas sequências, cada caractere pode ser "escapado" usando números hexadecimais, sendo possível usar pontos de código Unicode de até 0x10FFFF. Com escapes Unicode simples muitas vezes é necessário escrever as metades substitutas separadamente para obter o mesmo resultado.

+ +

Veja também {{jsxref("String.fromCodePoint()")}} or {{jsxref("String.prototype.codePointAt()")}}.

+ +
'\u{2F804}'
+
+// o mesmo com escapes Unicode simples
+'\uD87E\uDC04'
+ +

Objetos String

+ +

O objeto {{jsxref("String")}} é como uma "capa" ao redor do tipo primitivo string.

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

Você pode chamar qualquer um dos métodos do objeto String em cima de uma string literal — JavaScript automaticamente converte a string literal em um objeto String temporário, chama o método, e então descarta o objeto String temporário. Você pode também usar a propriedade String.length com uma string literal.

+ +

Você deve usar strings literais a menos que você realmente precise usar um objeto String, pois objetos String podem ter comportamentos inesperados. Por exemplo:

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

Um objeto String possui uma propriedade, length, que indica o número de caracteres na string. Por exemplo, o código a seguir atribui o valor 11 à variável x, pois "Olá, mundo!" possui 11 caracteres:

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

Um objeto String possui uma variedade de métodos: por exemplo aqueles que retornam uma variação da própria string, como substring e toUpperCase.

+ +

A tabela a seguir lista os métodos de objetos {{jsxref("String")}}.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Métodos de String

+
MétodoDescrição
{{jsxref("String.charAt", "charAt")}}, {{jsxref("String.charCodeAt", "charCodeAt")}}, {{jsxref("String.codePointAt", "codePointAt")}}Retorna o código do caractere ou o caractere em uma posição específica na string.
{{jsxref("String.indexOf", "indexOf")}}, {{jsxref("String.lastIndexOf", "lastIndexOf")}}Retorna a posição de uma substring específica na string ou a última posição da substring específica, respectivamente.
{{jsxref("String.startsWith", "startsWith")}}, {{jsxref("String.endsWith", "endsWith")}}, {{jsxref("String.includes", "includes")}}Retorna se uma string começa, termina ou contém uma outra string específica.
{{jsxref("String.concat", "concat")}}Concatena o texto de duas strings e retorna uma nova string.
{{jsxref("String.fromCharCode", "fromCharCode")}}, {{jsxref("String.fromCodePoint", "fromCodePoint")}}Cria uma string a partir de uma sequência específica de valores Unicode. Esse é um método da classe String, não de uma instância do tipo String.
{{jsxref("String.split", "split")}}Separa um objeto String em um array de strings, separando a string em substrings.
{{jsxref("String.slice", "slice")}}Extrai uma seção de uma string e retorna uma nova string.
{{jsxref("String.substring", "substring")}}, {{jsxref("String.substr", "substr")}}Retorna um subconjunto específico de uma string, definindo os índices inicial e final, ou definindo um índice e um tamanho.
{{jsxref("String.match", "match")}}, {{jsxref("String.replace", "replace")}}, {{jsxref("String.search", "search")}}Trabalha com expressões regulares.
{{jsxref("String.toLowerCase", "toLowerCase")}}, {{jsxref("String.toUpperCase", "toUpperCase")}} +

Retorna a string com todos caracteres em minúsculo, ou maiúsculo, respectivamente.

+
{{jsxref("String.normalize", "normalize")}}Retorna a Forma Normalizada Unicode (Unicode Normalization Form) da string que chama o método.
{{jsxref("String.repeat", "repeat")}}Retorna uma string contendo os elementos do objeto repetidos pela quantidade de vezes dada.
{{jsxref("String.trim", "trim")}}Retira espaços em branco no começo e no final da string.
+ +

Template strings com várias linhas

+ +

Template strings são strings literais que permitem expressões no seu conteúdo. Você pode usar os recursos de strings com multiplas linhas e interpolações de string com as template strings.

+ +

Template strings são declaradas com o acento grave (``) ao invés de aspas simples ou aspas duplas. Essas strings podem conter place holders. Os place holders são indicados pelo cifrão e com chaves ( ${expressao} ).

+ +

Várias linhas (Multi-lines)

+ +

Qualquer caractere de nova linha ( '\n' ) inserido na string também faz parte das template string. Usando strings normais, você teria que usar a sintaxe a seguir para conseguir uma string de várias linhas

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

Para obter o mesmo efeito com strings multi-lines, você pode agora escrever:

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

Expressões inseridas

+ +

Para conseguir inserir expressões com strings normais, você teria que usar a seguinte sintaxe:

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

Agora, com template strings, você tem a capacidade de usar uma forma mais simples e legível para fazer essas substituições:

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

Para mais informações, leia sobre Template strings na referência JavaScript.

+ +

Internacionalização

+ +

O objeto {{jsxref("Intl")}} é o namespace para a API de Internacionalização do ECMAScript, que oferece comparação de strings sensíveis à linguagem, formatação de números, e formatação de datas e horas. Os construtores para os objetos {{jsxref("Collator")}}, {{jsxref("NumberFormat")}}, e {{jsxref("DateTimeFormat")}} são propriedades do objeto Intl.

+ +

Formatação de data e hora

+ +

O objeto {{jsxref("DateTimeFormat")}} é útil para a formatação de data e hora. O código a seguir formata uma data em inglês no formato que é utilizado nos Estados Unidos. (O resultado é diferente em outro fuso horário).

+ +
var msPorDia = 24 * 60 * 60 * 1000; // número de milisegundos em um dia
+
+// July 17, 2014 00:00:00 UTC.
+var july172014 = new Date(msPorDia * (44 * 365 + 11 + 197));
+
+var opcoes = { year: "2-digit", month: "2-digit", day: "2-digit",
+                hour: "2-digit", minute: "2-digit", timeZoneName: "short" };
+var americanDateTime = new Intl.DateTimeFormat("en-US", opcoes).format;
+
+console.log(americanDateTime(july172014)); // 07/16/14, 5:00 PM PDT
+
+ +

Formatação de números

+ +

O objeto {{jsxref("NumberFormat")}} é útil para formatar números, por exemplo unidade monetária.

+ +
var precoGasolina = new Intl.NumberFormat("en-US",
+                        { style: "currency", currency: "USD",
+                          minimumFractionDigits: 3 });
+
+console.log(precoGasolina.format(5.259)); // $5.259
+
+var hanDecimalRMBInChina = new Intl.NumberFormat("zh-CN-u-nu-hanidec",
+                        { style: "currency", currency: "CNY" });
+
+console.log(hanDecimalRMBInChina.format(1314.25)); // ¥ 一,三一四.二五
+
+ +

Collation

+ +

O objeto {{jsxref("Collator")}} é usado para comparar e ordenar strings.

+ +

Por exemplo, existem atualmente duas ordens diferentes de classificação no Alemão: listaTelefônica e dicionário. A ordenação da listaTelefônica enfatiza o som, e é como se "ä", "ö", e assim por diante, fossem expandidos para "ae", "oe", e assim sucessivamente, para definir a ordem.

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

Algumas palavras do alemão são conjugadas com tremas extras, mas no dicionário essas palavras são ordenadas ignorando os tremas (exceto quando ordenando palavras que tem apenas o trema como diferença: schon antes de schön).

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

Para mais informação sobre a API {{jsxref("Intl")}}, veja também Introducing the JavaScript Internationalization API (em inglês).

+ +
{{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
diff --git a/files/pt-br/web/javascript/guide/trabalhando_com_objetos/index.html b/files/pt-br/web/javascript/guide/trabalhando_com_objetos/index.html deleted file mode 100644 index 1dccaeef2e..0000000000 --- a/files/pt-br/web/javascript/guide/trabalhando_com_objetos/index.html +++ /dev/null @@ -1,494 +0,0 @@ ---- -title: Trabalhando com objetos -slug: Web/JavaScript/Guide/Trabalhando_com_Objetos -tags: - - Comparando Objetos - - Contrutor - - Documento - - ECMAScript6 - - Guia(2) - - Iniciante - - JavaScript -translation_of: Web/JavaScript/Guide/Working_with_Objects ---- -

A linguagem JavaScript é projetada com base em um simples paradigma orientado a objeto. Um objeto é uma coleção de propriedades, e uma propriedade é uma associação entre um nome (ou chave) e um valor. Um valor de propriedade pode ser uma função, que é então considerada um método do objeto. Além dos objetos que são pré-definidos no browser, você pode definir seus próprios objetos.

- -

Este capítulo descreve como usar objetos, propriedades, funções, e métodos, e como criar seus próprios objetos.

- -

Visão geral de objetos

- -

Objetos em JavaScript, assim como em muitas outras linguagens de programação, podem ser comparados com objetos na vida real. O conceito de objetos em JavaScript pode ser entendido com objetos tangíveis da vida real.

- -

Em JavaScript, um objeto é uma entidade independente, com propriedades e tipos. Compare-o com uma xícara, por exemplo. Uma xícara é um objeto, com propriedades. Uma xícara tem uma cor, uma forma, peso, um material de composição, etc. Da mesma forma, objetos em JavaScript podem ter propriedades, que definem suas características.

- -

Objetos e propriedades

- -

Um objeto em JavaScript tem propriedades associadas a ele. Uma propriedade de um objeto pode ser explicada como uma variável que é ligada ao objeto. Propriedades de objetos são basicamente as mesmas que variáveis normais em JavaScript, exceto pelo fato de estarem ligadas a objetos. As propriedades de um objeto definem as características do objeto. Você acessa as propriedades de um objeto com uma simples notação de ponto:

- -
-
nomeDoObjeto.nomeDaPropriedade
-
-
- -

Como as variáveis em JavaScript, o nome do objeto (que poderia ser uma variável normal) e um nome de propriedade diferem em maiúsculas/minúsculas (por exemplo, cor e Cor são propriedades diferentes). Você pode definir uma propriedade atribuindo um valor a ela. Por exemplo, vamos criar um objeto chamado meuCarro e dar a ele propriedades chamadas fabricacao, modelo, e ano, conforme mostrado a seguir:

- -
var meuCarro = new Object();
-meuCarro.fabricacao = "Ford";
-meuCarro.modelo = "Mustang";
-meuCarro.ano = 1969;
-
- -

Propriedades não definidas de um objeto são {{jsxref("undefined")}} (e não {{jsxref("null")}}).

- -
meuCarro.semPropriedade; //undefined
- -

Propriedades de objetos em JavaScript podem também ser acessadas ou alteradas usando-se notação de colchetes. Objetos são às vezes chamados de arrays associativos, uma vez que cada propriedade é associada com um valor de string que pode ser usado para acessá-la. Então, por exemplo, você poderia acessar as propriedades do objeto meuCarro como se segue:

- -
meuCarro["fabricacao"] = "Ford";
-meuCarro["modelo"] = "Mustang";
-meuCarro["ano"] = 1969;
-
- -

Um nome de propriedade de um objeto pode ser qualquer string JavaScript válida, ou qualquer coisa que possa ser convertida em uma string, incluindo uma string vazia. No entanto, qualquer nome e propriedade que não é um identificador JavaScript válido (por exemplo, um nome de propriedade que tem um espaço ou um hífen, ou que começa com um número) só pode ser acessado(a) usando-se a notação de colchetes. Essa notação é também muito útil quando nomes de propriedades devem ser determinados dinamicamente (quando o nome da propriedade não é determinado até o momento de execução). Exemplos são mostrados a seguir:

- -
var meuObj = new Object(),
-    str = "minhaString",
-    aleat = Math.random(),
-    obj = new Object();
-
-meuObj.tipo               = "Sintaxe de ponto";
-meuObj["data de criacao"] = "String com espaco";
-meuObj[str]               = "valor de String";
-meuObj[aleat]             = "Numero Aleatorio";
-meuObj[obj]               = "Objeto";
-meuObj[""]                = "Mesmo uma string vazia";
-
-console.log(meuObj);
-
- -

Você pode também acessar propriedades usando um valor de string que está armazenado em uma variável:

- -
-
var nomeDaPropriedade = "fabricacao";
-meuCarro[nomeDaPropriedade] = "Ford";
-
-nomeDaPropriedade = "modelo";
-meuCarro[nomeDaPropriedade] = "Mustang";
-
-
- -

Você pode usar a notação de colchetes com o comando for...in para iterar por todas as propriedades enumeráveis de um objeto. Para ilustrar como isso funciona, a seguinte função mostra as propriedades de um objeto quando você passa o objeto e o nome do objeto como argumentos para a função:

- -
function mostrarProps(obj, nomeDoObj) {
-  var resultado = "";
-  for (var i in obj) {
-    if (obj.hasOwnProperty(i)) {
-        resultado += nomeDoObj + "." + i + " = " + obj[i] + "\n";
-    }
-  }
-  return resultado;
-}
-
- -

Então, a chamada de função mostrarProps(meuCarro, "meuCarro") retornaria o seguinte:

- -
meuCarro.fabricacao = Ford
-meuCarro.modelo = Mustang
-meuCarro.ano = 1969
- -

Objetos: tudo

- -

Em JavaScript, quase tudo é um objeto. Todos os tipos primitivos - com exceção de null e undefined - são tratados como objetos. Eles podem receber propriedades (propriedades atribuídas de alguns tipos não são persistentes), e possuem todas as características de objetos.

- -

Enumerando todas as propriedades de um objeto

- -

Começando com a ECMAScript 5, há três formas nativas de se listar (ou "caminhar por") as propriedades de um objeto:

- - - -

Antes, na ECMAScript 5, não existia uma forma nativa de se listar todas as propriedades de um objeto. No entanto, isso pode ser feito com a seguinte função:

- -
function listarTodasAsPropriedades(o){
-	var objectoASerInspecionado;
-	var resultado = [];
-
-	for(objectoASerInspecionado = o; objectoASerInspecionado !== null; objectoASerInspecionado = Object.getPrototypeOf(objectoASerInspecionado)){
-		resultado = resultado.concat(Object.getOwnPropertyNames(objectoASerInspecionado));
-	}
-
-	return resultado;
-}
-
- -

Isso pode ser útil para revelar propriedades "escondidadas" (propriedades na cadeia de protótipos que não são acessíveis através do objeto, porque outra propriedade possui o mesmo nome anteriormente na cadeia de protótipos). A listagem de propriedades acessíveis só pode ser facilmente feita através da remoção de valores duplicados no array.

- -

Criando novos objetos

- -

JavaScript possui um número de objetos pré-definidos. Além disso, você pode criar seus próprios objetos. Você pode criar um objeto usando um objeto inicializador. Alternativamente, você pode primeiro criar uma função construtora e depois instanciar um objeto usando aquela função e o operador new.

- -

Usando inicializadores de objeto

- -

Além de criar objetos usando uma função construtora, você pode criar objetos usando um inicializador de objeto. O uso de inicializadores de objeto é às vezes conhecido como criar objetos com notação literal. O termo "inicializador de objeto" é consistente com a terminologia usada por C++.

- -

A sintaxe para um objeto usando-se um inicializador de objeto é:

- -
var obj = { propriedade_1:   valor_1,   // propriedade_# pode ser um identificador...
-            2:            valor_2,   // ou um numero...
-            // ...,
-            "propriedade n": valor_n }; // ou uma string
-
- -

onde obj é o nome do novo objeto, cada propriedade_i é um identificador (um nome, um número, ou uma string literal), e cada valor_i é uma expressão cujo valor é atribuído à propriedade_i. O obj e a atribuição são opcionais; se você não precisa fazer referência a esse objeto em nenhum outro local, você não precisa atribuí-lo a uma variável. (Note que você pode precisar colocar o objeto literal entre parentêses se o objeto aparece onde um comando é esperado, de modo a não confundir o literal com uma declaração de bloco.)

- -

Se um objeto é criado com um inicializador de objeto em um script de alto nível, JavaScript interpreta o objeto a cada vez que avalia uma expressão contendo o objeto literal. Além disso, um inicializador usado em uma função é criado toda vez que a função é chamada.

- -

O seguinte comando cria um objeto e o atribui à variável x somente se a expressão cond é verdadeira.

- -
if (cond) var x = {hi: "there"};
-
- -

O seguinte exemplo cria minhaHonda com três propriedades. Note que a propriedade motor é também um objeto com suas próprias propriedades.

- -
var minhaHonda = {cor: "vermelho", rodas: 4, motor: {cilindros: 4, tamanho: 2.2}};
-
- -

Você pode também usar inicializadores de objeto para criar arrays. Veja arrays literais.

- -

Usando uma função construtora

- -

Alternativamente, você pode criar um objeto com estes dois passos:

- -
    -
  1. Defina o tipo de objeto escrevendo uma função construtora. Há uma forte convenção, e com boa razão, de se usar uma letra inicial maiúscula.
  2. -
  3. Crie uma instância do objeto com new.
  4. -
- -

Para definir um tipo de objeto, crie uma função para o tipo de objeto que especifique seu nome, suas propriedades e seus métodos. Por exemplo, suponha que você queira criar um tipo objeto para carros. Você quer que esse tipo de objeto seja chamado carro, e você quer ele tenha propriedades de marca, modelo, e ano. Para fazer isto, você escreveria a seguinte função:

- -
function Carro(marca, modelo, ano) {
-  this.marca = marca;
-  this.modelo = modelo;
-  this.ano = ano;
-}
-
- -

Note o uso de this para atribuir valores às propriedades do objeto com base nos valores passados para a função.

- -

Agora você pode criar um objeto chamado meucarro como se segue:

- -
var meucarro = new Carro("Eagle", "Talon TSi", 1993);
-
- -

Esse comando cria meucarro e atribui a ele valores especificados para suas propriedade. Então o valor de meucarro.marca é a string "Eagle", meucarro.ano é o inteiro 1993, e assim por diante.

- -

Você pode criar qualquer número de objetos carro com o uso de new. Exemplo,

- -
var carroDeKen = new Carro("Nissan", "300ZX", 1992);
-var carroDeVPG = new Carro("Mazda", "Miata", 1990);
-
- -

Um objeto pode ter uma propriedade que por si só também é um objeto. Por exemplo, suponha que você define um objeto chamado pessoa como se segue:

- -
function Pessoa(nome, idade, sexo) {
-  this.nome = nome;
-  this.idade = idade;
-  this.sexo = sexo;
-}
-
- -

e então você instancia dois novos objetos pessoa da seguinte forma:

- -
var jose = new Pessoa("Jose Silva", 33, "M");
-var paulo = new Pessoa("Paulo Santos", 39, "M");
-
- -

Então, você pode reescrever a definição de carro de modo a incluir uma propriedade dono que recebe um objeto pessoa, como se segue:

- -
function Carro(marca, modelo, ano, dono) {
-  this.marca = marca;
-  this.modelo = modelo;
-  this.ano = ano;
-  this.dono = dono;
-}
-
- -

Para instanciar os novos objetos, você então usa o seguinte:

- -
var carro1 = new Carro("Eagle", "Talon TSi", 1993, jose);
-var carro2 = new Carro("Nissan", "300ZX", 1992, paulo);
-
- -

Perceba que ao invés de passar uma string literal ou um valor inteiro na hora de criar os novos objetos, os comandos acima passam os objetos jose e paulo como os argumentos para os donos. Então se você quiser descobrir o nome do dono de carro2, você pode acessar a seguinte propriedade:

- -
carro2.dono
-
- -

Note que você pode sempre adicionar uma propriedade a um objeto definido anteriormente. Por exemplo, o comando

- -
carro1.cor = "preto";
-
- -

adiciona uma propriedade cor ao carro1, e dá a ele o valor "preto." No entanto, isso não afeta nenhum outro objeto. Para adicionar a nova propriedade a todos os objetos do mesmo tipo, você deve adicionar a propriedade na definição do tipo de objeto carro.

- -

Usando o método Object.create

- -

Objetos podem também ser criados usando-se o método Object.create(). Esse método pode ser muito útil, pois permite que você escolha o objeto protótipo para o objeto que você quer criar, sem a necessidade de se definir uma função construtora.

- -
// Encapsulamento das propriedades e métodos de Animal
-var Animal = {
-  tipo: "Invertebrados", // Propriedades de valores padrão
-  qualTipo : function() {  // Método que ira mostrar o tipo de Animal
-    console.log(this.tipo);
-  }
-}
-
-// Cria um novo tipo de animal chamado animal1
-var animal1 = Object.create(Animal);
-animal1.qualTipo(); // Saída:Invertebrados
-
-// Cria um novo tipo de animal chamado Peixes
-var peixe = Object.create(Animal);
-peixe.tipo = "Peixes";
-peixe.qualTipo(); // Saída: Peixes
- -

Herança

- -

Todos os objetos em JavaScript herdam de pelo menos um outro objeto. O objeto "pai" é conhecido como o protótipo, e as propriedades herdadas podem ser encontradas no objeto prototype do construtor.

- -

Indexando Propriedades de Objetos

- -

Você pode se referir a uma propriedade de um objeto pelo seu nome de propriedade ou pelo seu índice ordinal. Se você inicialmente definiu uma propriedade pelo nome, você deve sempre se referir a ela pelo nome, e se você inicialmente definir uma propriedade por um índice, você deve sempre se referir a ela pelo índice.

- -

Esta restrição se aplica quando  você cria um objeto e suas propriedades com uma função construtora (como fizemos anteriormente com o objeto do tipo carro) e quando você define propriedades individuais explicitamente (por exemplo, meuCarro.cor = "vermelho"). Se você inicialmente definir uma propriedade do objeto com um índice, tal como meuCarro[5] = "25 mpg", você pode subsequentemente referir-se á propriedade somente como meuCarro[5].

- -

A exceção a esta regra é a objetos refletidos a partir do HTML, como o conjunto de formulários. Você pode sempre se referir a objetos nessas matrizes por seu número de ordem (com base em onde eles aparecem no documento) ou seu nome (se definido). Por exemplo, se a segunda tag <FORM> em um  documento tem um atributo NAME de "meuFormulario", você pode se referir ao formulário como document.forms[1] ou document.forms["meuFormulario"] ou document.meuFormulario.

- -

Definindo propriedades para um tipo de objeto

- -

Você pode adicionar uma propriedade a um tipo de objeto definido anteriormente, utilizando a propriedade prototype. Esta define uma propriedade que é partilhada por todos os objetos do tipo especificado, em vez de apenas uma instância do objeto. O código a seguir adiciona uma propriedade cor para todos os objetos do tipo Carro, em seguida adiciona um valor a propriedade cor do objeto carro1.

- -
Carro.prototype.cor = null;
-carro1.cor = "preto";
-
- -

Consulte a propriedade prototype do objeto Function na Referência JavaScript  para mais informações.

- -

Definindo métodos

- -

Um método é uma função associada a um objeto, ou, simplesmente, um método é uma propriedade de um objeto que é uma função. Métodos são definidos da forma que as funções normais são definidas, exceto que eles tenham que ser atribuídos como propriedade de um objeto. São exemplos:

- -
nomeDoObjeto.nomedometodo = nome_da_funcao;
-
-var meuObjeto = {
-  meuMetodo: function(parametros) {
-    // ...faça algo
-  }
-};
-
- -

Onde nomeDoObjeto é um objeto existente, nomedometodo é o nome que você atribuiu ao método, e nome_da_funcao é o nome da função.

- -

Em seguida, você pode chamar o método no contexto do objeto da seguinte forma:

- -
objeto.nomedometodo(parametros);
-
- -

Você pode definir métodos para um tipo de objeto incluindo uma definição de metodo na função construtora do objeto. Por exemplo, você poderia definir uma função que iria formatar e mostrar as propriedades do objeto carro previamente definido; por exemplo,

- -
function mostreCarro() {
-  var resultado = "Um belo " + this.ano + " " + this.fabricacao
-    + " " + this.modelo;
-  pretty_print(resultado);
-}
-
- -

onde pretty_print é uma função que mostra uma linha horizontal e uma string. Observe o uso de this para referenciar o objeto ao qual o método pertence.

- -

Você pode fazer desta função um método de carro, adicionando seu estado à definição do objeto.

- -
this.mostreCarro = mostreCarro;
-
- -

Assim, a definição completa de carro seria agora, parecida com essa:

- -
function Carro(fabricacao, modelo, ano, proprietario) {
-  this.fabricacao = fabricacao;
-  this.modelo = modelo;
-  this.ano = ano;
-  this.proprietario = proprietario;
-  this.mostreCarro = mostreCarro;
-}
-
- -

Então você pode chamar o método mostreCarro para cada objeto seguinte:

- -
carro1.mostreCarro();
-carro2.mostreCarro();
-
- -

Usando this para referências de objetos

- -

JavaScript tem uma palavra-chave especial, this, que você pode usar dentro de um método para referenciar o objeto corrente. Por exemplo, suponha que você tenha uma função chamada validate que valida o valor da propriedade de um objeto, dado o objeto e os valores altos e baixos:

- -
function validate(obj, lowval, hival) {
-  if ((obj.value < lowval) || (obj.value > hival))
-    alert("Valor inválido!");
-}
-
- -

Então, você poderia chamar validate no manipulador de evento onchange em cada elemento do formulário, usando this para passar o elemento, como no exemplo a seguir:

- -
<input type="text" name="age" size="3"
-  onChange="validate(this, 18, 99)">
-
- -

No geral, this referencia o objeto chamando um método.

- -

Quando combinado com a propriedade form , this pode referenciar a forma original do objeto atual. No exemplo seguinte, o formulário myForm contém um objeto Text e um botão. Quando o usuário clica no botão, o valor do objeto Text é definido como nome do formulário. O manipulador de eventos onclick do botão usa this.form para referenciar a forma original, myForm.

- -
<form name="myForm">
-<p><label>Nome do form:<input type="text" name="text1" value="Beluga"></label>
-<p><input name="button1" type="button" value="Mostre o Nome do Form"
-     onclick="this.form.text1.value = this.form.name">
-</p>
-</form>
- -

Definindo getters e setters

- -

Um getter é um método que obtém o valor de uma propriedade específica. Um setter é um método que define o valor de uma propriedade específica. Você pode definir getters e setters em qualquer objeto de núcleo pré-definido ou objeto definido pelo usuário que suporta a adição de novas propriedades. A sintaxe para definir getters e setters usa a sintaxe literal do objeto.

- -

O código a seguir ilustra como getters e setters podem funcionar para um objeto o definido pelo usuário.

- -
var o = {
-  a: 7,
-  get b() {
-    return this.a + 1;
-  },
-  set c(x) {
-    this.a = x / 2
-  }
-};
-
-console.log(o.a); // 7
-console.log(o.b); // 8
-o.c = 50;
-console.log(o.a); // 25
- -

As propriedades do objeto o são:

- - - -

Observe que nomes de função de getters e setters definidos em um objeto literal usando "[gs]et property()" (ao contrário de __define[GS]etter__ ) não são os próprios nomes dos getters, embora a sintaxe [gs]et propertyName(){ } possa  induzir ao erro e você pensar de outra forma. Para nomear uma função getter ou setter usando a sintaxe "[gs]et property()", define explicitamente um função nomeada programaticamente usando Object.defineProperty (ou o legado fallback Object.prototype.__defineGetter__).

- -

O código a seguir ilustra como getters e setters podem extender o protótipo Date para adicionar a propriedade ano para todas as instâncias de classes Date pré-definidas. Ele usa os métodos getFullYear e setFullYear existentes da classe Date para suportar o getter e setter da propriedade ano.

- -

Estes estados definem um getter e setter para a propriedade ano:

- -
var d = Date.prototype;
-Object.defineProperty(d, "year", {
-  get: function() { return this.getFullYear() },
-  set: function(y) { this.setFullYear(y) }
-});
- -

Estes estados usam o getter e setter em um objeto Date:

- -
var now = new Date();
-console.log(now.year); // 2000
-now.year = 2001; // 987617605170
-console.log(now);
-// Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
- -

A principio, getters e setters podem ser ou

- - - -

Ao definir getters e setters usando objetos inicializadores tudo o que você precisa fazer é prefixar um método getter com get e um método setter com set. Claro, o método getter não deve esperar um parâmetro, enquanto o método setter espera exatamente um parâmetro (novo valor para definir). Por exemplo:

- -
var o = {
-  a: 7,
-  get b() { return this.a + 1; },
-  set c(x) { this.a = x / 2; }
-};
-
- -

Getters e setters podem também ser adicionado em um objeto a qualquer hora depois da criação usando o método Object.defineProperties. O primeiro parâmetro deste método é o objeto no qual você quer definir o getter ou setter. O segundo parâmetro é um objeto cujos nomes das propriedades são os nomes getter ou setter, e cujo valores das propriedades são objetos para definição de funções getter ou setter. Aqui está um exemplo que define o mesmo getter e setter usado no exemplo anterior:
-  

- -
var o = { a:0 }
-
-Object.defineProperties(o, {
-    "b": { get: function () { return this.a + 1; } },
-    "c": { set: function (x) { this.a = x / 2; } }
-});
-
-o.c = 10 // Roda o setter, que associa 10 / 2 (5) para a propriedade 'a'
-console.log(o.b) // Roda o getter, que yields a + 1 ou 6
-
- -

Escolher qual das duas formas depende do seu estilo de programação e tarefa na mão. Se você já vai para o inicializador de objeto ao definir um protótipo, provavelmente a maior parte do tempo escolherá a primeira forma. Esta forma é mais compacta e natural. No entanto, se você precisar adicionar getters e setters mais tarde - porque você não escreveu o protótipo ou objeto particular - então a segunda forma é a única possível. A segunda forma provavelmente melhor representa a natureza dinâmica do JavaScript - mas pode tornar o código difícil de ler e entender.

- -

Removendo propriedades

- -

Você pode remover uma propriedade não herdada usando o operador delete. O código a seguir mostra como remover uma propriedade.

- -
//Criando um novo objeto, myobj, com duas propriedades, a e b.
-var myobj = new Object;
-myobj.a = 5;
-myobj.b = 12;
-
-//Removendo a propriedade a, deixando myobj com apenas a propriedade b.
-delete myobj.a;
-console.log ("a" in myobj) // yields "false"
-
- -

Você também pode usar delete para remover uma variável global se a var keyword não estiver sendo usada para declarar a variável:

- -
g = 17;
-delete g;
-
- -

Comparando Objetos

- -

Em JavaScript, objetos são um tipo de referência. Dois objetos distintos nunca são iguais, mesmo que tenham as mesmas propriedades. Apenas comparando o mesmo objeto de referência com ele mesmo produz verdadeiro.

- -
// Duas variáveis, dois objetos distintos com as mesmas propriedades
-var fruit = {name: "apple"};
-var fruitbear = {name: "apple"};
-
-fruit == fruitbear // return false
-fruit === fruitbear // return false
- -
// Duas variáveis, um único objeto
-var fruit = {name: "apple"};
-var fruitbear = fruit;  // assign fruit object reference to fruitbear
-
-// Here fruit and fruitbear are pointing to same object
-fruit == fruitbear // return true
-fruit === fruitbear // return true
- -

Para mais informações sobre comparaçāo de operadores, veja Operadores de comparaçāo.

- -

Veja também

- - - -
{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}
diff --git a/files/pt-br/web/javascript/guide/usando_promises/index.html b/files/pt-br/web/javascript/guide/usando_promises/index.html deleted file mode 100644 index a0dd09c8c2..0000000000 --- a/files/pt-br/web/javascript/guide/usando_promises/index.html +++ /dev/null @@ -1,269 +0,0 @@ ---- -title: Usando promises -slug: Web/JavaScript/Guide/Usando_promises -tags: - - Guía - - Intermediário - - JavaScript - - Promise - - Promises -translation_of: Web/JavaScript/Guide/Using_promises ---- -
{{jsSidebar("JavaScript Guide")}}{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}
- -

Uma {{jsxref("Promise")}} é um objeto que representa a eventual conclusão ou falha de uma operação assincrona. Como a maioria das pessoas consomem promisses já criadas, este guia explicará o consumo de promisses devolvidas antes de explicar como criá-las.

- -

Essencialmente, uma promise é um objeto retornado para o qual você adiciona callbacks, em vez de passar callbacks para uma função.

- -

Por exemplo, em vez de uma função old-style que espera dois callbacks, e chama um deles em uma eventual conclusão ou falha:

- -
function successCallback(result) {
-  console.log("It succeeded with " + result);
-}
-
-function failureCallback(error) {
-  console.log("It failed with " + error);
-}
-
-doSomething(successCallback, failureCallback);
- -

…funções modernas retornam uma promisse e então você pode adicionar seus callbacks:

- -
const promise = doSomething();
-promise.then(successCallback, failureCallback);
- -

…ou simplesmente:

- -
doSomething().then(successCallback, failureCallback);
- -

Nós chamamos isso de chamada de função assincrona. Essa convenção tem várias vantagens. Vamos explorar cada uma delas.

- -

Garantias

- -

Ao contrário dos callbacks com retornos de funções old-style, uma promisse vem com algumas garantias:

- - - -

Mas o benefício mais imediato da promises é o encadeamento.

- - - -

Encadeamento

- -

Uma necessidade comum é executar duas ou mais operações assincronas consecutivas, onde cada operação subsequente começa quando a operação anterior é bem sucedida, com o resultado do passo anterior. Nós conseguimos isso criando uma cadeia de promises.

- -

Aqui está a magica: a função then retorna uma nova promise, diferente da original:

- -
const promise = doSomething();
-const promise2 = promise.then(successCallback, failureCallback);
-
- -

ou

- -
const promise2 = doSomething().then(successCallback, failureCallback);
-
- -

Essa segunda promise representa a conclusão não apenas de doSomething(), mas também do successCallback ou failureCallback que você passou, que podem ser outras funções assincronas que retornam uma promise. Quando esse for o caso, quaisquer callbacks adicionados a promise2 serão enfileiradas atrás da promise retornada por successCallback ou failureCallback.

- -

Basicamente, cada promise representa a completude de outro passo assíncrono na cadeia.

- -

Antigamente, realizar operações assíncronas comuns em uma linha levaria à clássica pirâmide da desgraça :

- -
doSomething(function(result) {
-  doSomethingElse(result, function(newResult) {
-    doThirdThing(newResult, function(finalResult) {
-      console.log('Got the final result: ' + finalResult);
-    }, failureCallback);
-  }, failureCallback);
-}, failureCallback);
-
- -

Ao invés disso, com funções modernas, nós atribuímos nossas callbacks às promises retornadas, formando uma cadeia de promise:

- -
doSomething().then(function(result) {
-  return doSomethingElse(result);
-})
-.then(function(newResult) {
-  return doThirdThing(newResult);
-})
-.then(function(finalResult) {
-  console.log('Got the final result: ' + finalResult);
-})
-.catch(failureCallback);
-
- -

Os argumentos para then são opcionais, e catch(failureCallback) é uma abreviação para then(null, failureCallback). Você pode também pode ver isso escrito com arrow functions:

- -
doSomething()
-.then(result => doSomethingElse(result))
-.then(newResult => doThirdThing(newResult))
-.then(finalResult => {
-  console.log(`Got the final result: ${finalResult}`);
-})
-.catch(failureCallback);
-
- -

Importante: Sempre retorne um resultado, de outra forma as callbacks não vão capturar o resultado da promise anterior.

- -

Encadeando depois de um catch

- -

É possivel encadear depois de uma falha, i.e um catch, isso é muito útil para realizar novas ações mesmo depois de uma falha no encadeamento. Leia o seguinte exemplo: 

- -
new Promise((resolve, reject) => {
-    console.log('Initial');
-
-    resolve();
-})
-.then(() => {
-    throw new Error('Something failed');
-
-    console.log('Do this');
-})
-.catch(() => {
-    console.log('Do that');
-})
-.then(() => {
-    console.log('Do this whatever happened before');
-});
-
- -

Isso vai produzir o seguinte texto:

- -
Initial
-Do that
-Do this whatever happened before
-
- -

Observe que o texto "Do this" não foi impresso por conta que o erro "Something failed" causou uma rejeição.

- -

Propagação de erros

- -

Na pirâmide da desgraça vista anteriormente, você pode se lembrar de ter visto failureCallback três vezes, em comparação a uma única vez no fim da corrente de promessas:

- -
doSomething()
-.then(result => doSomethingElse(result))
-.then(newResult => doThirdThing(newResult))
-.then(finalResult => console.log(`Got the final result: ${finalResult}`))
-.catch(failureCallback);
-
- -

Basicamente, uma corrente de promessas para se houver uma exceção, procurando por catch handlers no lugar. Essa modelagem de código segue bastante a maneira de como o código síncrono funciona:

- -
try {
-  const result = syncDoSomething();
-  const newResult = syncDoSomethingElse(result);
-  const finalResult = syncDoThirdThing(newResult);
-  console.log(`Got the final result: ${finalResult}`);
-} catch(error) {
-  failureCallback(error);
-}
-
- -

Essa simetria com código assíncrono resulta no syntactic sugar async/await presente no ECMAScript 2017:

- -
async function foo() {
-  try {
-    const result = await doSomething();
-    const newResult = await doSomethingElse(result);
-    const finalResult = await doThirdThing(newResult);
-    console.log(`Got the final result: ${finalResult}`);
-  } catch(error) {
-    failureCallback(error);
-  }
-}
-
- -

É construído sobre promesas, por exemplo, doSomething() é a mesma função que antes. Leia mais sobre a sintaxe aqui.

- -

Por pegar todos os erros, até mesmo exceções jogadas(thrown exceptions) e erros de programação, as promises acabam por solucionar uma falha fundamental presente na pirâmide da desgraça dos callbacks. Essa característica é essencial para a composição funcional das operações assíncronas.

- -

Criando uma Promise em torno de uma callback API antiga

- -

Uma {{jsxref("Promise")}} pode ser criada do zero utilizando o seu construtor. Isto deve ser necessário apenas para o envolvimento de APIs antigas.

- -

Em um mundo ideal, todas as funções assincronas já retornariam promises. Infelizmente, algumas APIs ainda esperam que os retornos de suceso e/ou falha sejam passados da maneira antiga. O exemplo por excelência é o {{domxref("WindowTimers.setTimeout", "setTimeout()")}} function:

- -
setTimeout(() => saySomething("10 seconds passed"), 10000);
-
- -

Misturar chamadas de retorno e promeses de old-style é problemático. Se saySomething falhar ou contiver um erro de programação, nada o captura.

- -

Por sorte nós podemos envolve-la em uma promise. É uma boa prática envolver funções problemáticas no menor nivel possível, e nunca chama-las diretamente de novo:

- -
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
-
-wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);
-
- -

Basically, the promise constructor takes an executor function that lets us resolve or reject a promise manually. Since setTimeout doesn't really fail, we left out reject in this case.

- -

Basicamente, um construtor de promises pega uma função executora que nos deixa resolver ou rejeitar uma promise manualmente. Desde que setTimeout não venha a falhar, nos deixamos a rejeição de fora nesse caso

- -

Composição

- -

{{jsxref("Promise.resolve()")}} e {{jsxref("Promise.reject()")}} são atalhos para se criar manualmente uma promessa que já foi resolvida ou rejeitada, respectivamente. Isso pode ser útil em algumas situações.

- -

{{jsxref("Promise.all()")}} e {{jsxref("Promise.race()")}} são duas ferramentas de composição para se executar operações assíncronas em paralelo.

- -

Uma composição sequencial é possível usando JavaScript de uma forma esperta:

- -
[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());
-
- -

Basicamente reduzimos um vetor de funções assíncronas a uma cadeia de promessas equivalentes a: Promise.resolve().then(func1).then(func2);

- -

Isso também pode ser feito com uma função de composição reutilizável, que é comum em programação funcional:

- -
const applyAsync = (acc,val) => acc.then(val);
-const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
- - - -

A função composeAsync aceitará qualquer número de funções como argumentos e retornará uma nova função que aceita um valor incial a ser passado pelo pipeline de composição. Isso é benéfico porque alguma, ou todas as funções, podem ser assíncronas ou síncronas, e é garantido de que serão executadas na ordem correta.

- -
const transformData = composeAsync(func1, asyncFunc1, asyncFunc2, func2);
-transformData(data);
-
- -

No ECMAScript 2017, uma composição sequencial pode ser feita sde forma mais simples com async/await:

- -
for (const f of [func1, func2]) {
-  await f();
-}
-
- -

Cronometragem

- -

Para evitar surpresas, funções passadas para then nunca serão chamadas sincronamente, mesmo com uma função ja resolvida:

- -
Promise.resolve().then(() => console.log(2));
-console.log(1); // 1, 2
-
- -

Instead of running immediately, the passed-in function is put on a microtask queue, which means it runs later when the queue is emptied at the end of the current run of the JavaScript event loop, i.e. pretty soon:

- -

Ao invés de rodar imediatamente, a função passada é colocada em uma micro tarefa, o que significa que ela roda depois que a fila estiver vazia no final do atual processo de evento de loop do Javascript, isto é muito em breve

- -
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
-
-wait().then(() => console.log(4));
-Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
-console.log(1); // 1, 2, 3, 4
-
- -

Ver também

- - - -

{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}

diff --git a/files/pt-br/web/javascript/guide/using_promises/index.html b/files/pt-br/web/javascript/guide/using_promises/index.html new file mode 100644 index 0000000000..a0dd09c8c2 --- /dev/null +++ b/files/pt-br/web/javascript/guide/using_promises/index.html @@ -0,0 +1,269 @@ +--- +title: Usando promises +slug: Web/JavaScript/Guide/Usando_promises +tags: + - Guía + - Intermediário + - JavaScript + - Promise + - Promises +translation_of: Web/JavaScript/Guide/Using_promises +--- +
{{jsSidebar("JavaScript Guide")}}{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}
+ +

Uma {{jsxref("Promise")}} é um objeto que representa a eventual conclusão ou falha de uma operação assincrona. Como a maioria das pessoas consomem promisses já criadas, este guia explicará o consumo de promisses devolvidas antes de explicar como criá-las.

+ +

Essencialmente, uma promise é um objeto retornado para o qual você adiciona callbacks, em vez de passar callbacks para uma função.

+ +

Por exemplo, em vez de uma função old-style que espera dois callbacks, e chama um deles em uma eventual conclusão ou falha:

+ +
function successCallback(result) {
+  console.log("It succeeded with " + result);
+}
+
+function failureCallback(error) {
+  console.log("It failed with " + error);
+}
+
+doSomething(successCallback, failureCallback);
+ +

…funções modernas retornam uma promisse e então você pode adicionar seus callbacks:

+ +
const promise = doSomething();
+promise.then(successCallback, failureCallback);
+ +

…ou simplesmente:

+ +
doSomething().then(successCallback, failureCallback);
+ +

Nós chamamos isso de chamada de função assincrona. Essa convenção tem várias vantagens. Vamos explorar cada uma delas.

+ +

Garantias

+ +

Ao contrário dos callbacks com retornos de funções old-style, uma promisse vem com algumas garantias:

+ + + +

Mas o benefício mais imediato da promises é o encadeamento.

+ + + +

Encadeamento

+ +

Uma necessidade comum é executar duas ou mais operações assincronas consecutivas, onde cada operação subsequente começa quando a operação anterior é bem sucedida, com o resultado do passo anterior. Nós conseguimos isso criando uma cadeia de promises.

+ +

Aqui está a magica: a função then retorna uma nova promise, diferente da original:

+ +
const promise = doSomething();
+const promise2 = promise.then(successCallback, failureCallback);
+
+ +

ou

+ +
const promise2 = doSomething().then(successCallback, failureCallback);
+
+ +

Essa segunda promise representa a conclusão não apenas de doSomething(), mas também do successCallback ou failureCallback que você passou, que podem ser outras funções assincronas que retornam uma promise. Quando esse for o caso, quaisquer callbacks adicionados a promise2 serão enfileiradas atrás da promise retornada por successCallback ou failureCallback.

+ +

Basicamente, cada promise representa a completude de outro passo assíncrono na cadeia.

+ +

Antigamente, realizar operações assíncronas comuns em uma linha levaria à clássica pirâmide da desgraça :

+ +
doSomething(function(result) {
+  doSomethingElse(result, function(newResult) {
+    doThirdThing(newResult, function(finalResult) {
+      console.log('Got the final result: ' + finalResult);
+    }, failureCallback);
+  }, failureCallback);
+}, failureCallback);
+
+ +

Ao invés disso, com funções modernas, nós atribuímos nossas callbacks às promises retornadas, formando uma cadeia de promise:

+ +
doSomething().then(function(result) {
+  return doSomethingElse(result);
+})
+.then(function(newResult) {
+  return doThirdThing(newResult);
+})
+.then(function(finalResult) {
+  console.log('Got the final result: ' + finalResult);
+})
+.catch(failureCallback);
+
+ +

Os argumentos para then são opcionais, e catch(failureCallback) é uma abreviação para then(null, failureCallback). Você pode também pode ver isso escrito com arrow functions:

+ +
doSomething()
+.then(result => doSomethingElse(result))
+.then(newResult => doThirdThing(newResult))
+.then(finalResult => {
+  console.log(`Got the final result: ${finalResult}`);
+})
+.catch(failureCallback);
+
+ +

Importante: Sempre retorne um resultado, de outra forma as callbacks não vão capturar o resultado da promise anterior.

+ +

Encadeando depois de um catch

+ +

É possivel encadear depois de uma falha, i.e um catch, isso é muito útil para realizar novas ações mesmo depois de uma falha no encadeamento. Leia o seguinte exemplo: 

+ +
new Promise((resolve, reject) => {
+    console.log('Initial');
+
+    resolve();
+})
+.then(() => {
+    throw new Error('Something failed');
+
+    console.log('Do this');
+})
+.catch(() => {
+    console.log('Do that');
+})
+.then(() => {
+    console.log('Do this whatever happened before');
+});
+
+ +

Isso vai produzir o seguinte texto:

+ +
Initial
+Do that
+Do this whatever happened before
+
+ +

Observe que o texto "Do this" não foi impresso por conta que o erro "Something failed" causou uma rejeição.

+ +

Propagação de erros

+ +

Na pirâmide da desgraça vista anteriormente, você pode se lembrar de ter visto failureCallback três vezes, em comparação a uma única vez no fim da corrente de promessas:

+ +
doSomething()
+.then(result => doSomethingElse(result))
+.then(newResult => doThirdThing(newResult))
+.then(finalResult => console.log(`Got the final result: ${finalResult}`))
+.catch(failureCallback);
+
+ +

Basicamente, uma corrente de promessas para se houver uma exceção, procurando por catch handlers no lugar. Essa modelagem de código segue bastante a maneira de como o código síncrono funciona:

+ +
try {
+  const result = syncDoSomething();
+  const newResult = syncDoSomethingElse(result);
+  const finalResult = syncDoThirdThing(newResult);
+  console.log(`Got the final result: ${finalResult}`);
+} catch(error) {
+  failureCallback(error);
+}
+
+ +

Essa simetria com código assíncrono resulta no syntactic sugar async/await presente no ECMAScript 2017:

+ +
async function foo() {
+  try {
+    const result = await doSomething();
+    const newResult = await doSomethingElse(result);
+    const finalResult = await doThirdThing(newResult);
+    console.log(`Got the final result: ${finalResult}`);
+  } catch(error) {
+    failureCallback(error);
+  }
+}
+
+ +

É construído sobre promesas, por exemplo, doSomething() é a mesma função que antes. Leia mais sobre a sintaxe aqui.

+ +

Por pegar todos os erros, até mesmo exceções jogadas(thrown exceptions) e erros de programação, as promises acabam por solucionar uma falha fundamental presente na pirâmide da desgraça dos callbacks. Essa característica é essencial para a composição funcional das operações assíncronas.

+ +

Criando uma Promise em torno de uma callback API antiga

+ +

Uma {{jsxref("Promise")}} pode ser criada do zero utilizando o seu construtor. Isto deve ser necessário apenas para o envolvimento de APIs antigas.

+ +

Em um mundo ideal, todas as funções assincronas já retornariam promises. Infelizmente, algumas APIs ainda esperam que os retornos de suceso e/ou falha sejam passados da maneira antiga. O exemplo por excelência é o {{domxref("WindowTimers.setTimeout", "setTimeout()")}} function:

+ +
setTimeout(() => saySomething("10 seconds passed"), 10000);
+
+ +

Misturar chamadas de retorno e promeses de old-style é problemático. Se saySomething falhar ou contiver um erro de programação, nada o captura.

+ +

Por sorte nós podemos envolve-la em uma promise. É uma boa prática envolver funções problemáticas no menor nivel possível, e nunca chama-las diretamente de novo:

+ +
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);
+
+ +

Basically, the promise constructor takes an executor function that lets us resolve or reject a promise manually. Since setTimeout doesn't really fail, we left out reject in this case.

+ +

Basicamente, um construtor de promises pega uma função executora que nos deixa resolver ou rejeitar uma promise manualmente. Desde que setTimeout não venha a falhar, nos deixamos a rejeição de fora nesse caso

+ +

Composição

+ +

{{jsxref("Promise.resolve()")}} e {{jsxref("Promise.reject()")}} são atalhos para se criar manualmente uma promessa que já foi resolvida ou rejeitada, respectivamente. Isso pode ser útil em algumas situações.

+ +

{{jsxref("Promise.all()")}} e {{jsxref("Promise.race()")}} são duas ferramentas de composição para se executar operações assíncronas em paralelo.

+ +

Uma composição sequencial é possível usando JavaScript de uma forma esperta:

+ +
[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());
+
+ +

Basicamente reduzimos um vetor de funções assíncronas a uma cadeia de promessas equivalentes a: Promise.resolve().then(func1).then(func2);

+ +

Isso também pode ser feito com uma função de composição reutilizável, que é comum em programação funcional:

+ +
const applyAsync = (acc,val) => acc.then(val);
+const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
+ + + +

A função composeAsync aceitará qualquer número de funções como argumentos e retornará uma nova função que aceita um valor incial a ser passado pelo pipeline de composição. Isso é benéfico porque alguma, ou todas as funções, podem ser assíncronas ou síncronas, e é garantido de que serão executadas na ordem correta.

+ +
const transformData = composeAsync(func1, asyncFunc1, asyncFunc2, func2);
+transformData(data);
+
+ +

No ECMAScript 2017, uma composição sequencial pode ser feita sde forma mais simples com async/await:

+ +
for (const f of [func1, func2]) {
+  await f();
+}
+
+ +

Cronometragem

+ +

Para evitar surpresas, funções passadas para then nunca serão chamadas sincronamente, mesmo com uma função ja resolvida:

+ +
Promise.resolve().then(() => console.log(2));
+console.log(1); // 1, 2
+
+ +

Instead of running immediately, the passed-in function is put on a microtask queue, which means it runs later when the queue is emptied at the end of the current run of the JavaScript event loop, i.e. pretty soon:

+ +

Ao invés de rodar imediatamente, a função passada é colocada em uma micro tarefa, o que significa que ela roda depois que a fila estiver vazia no final do atual processo de evento de loop do Javascript, isto é muito em breve

+ +
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait().then(() => console.log(4));
+Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
+console.log(1); // 1, 2, 3, 4
+
+ +

Ver também

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}

diff --git a/files/pt-br/web/javascript/guide/values,_variables,_and_literals/index.html b/files/pt-br/web/javascript/guide/values,_variables,_and_literals/index.html deleted file mode 100644 index 7920ee6b1a..0000000000 --- a/files/pt-br/web/javascript/guide/values,_variables,_and_literals/index.html +++ /dev/null @@ -1,601 +0,0 @@ ---- -title: Sintaxe e tipos -slug: 'Web/JavaScript/Guide/Values,_variables,_and_literals' -tags: - - Guia(2) - - Guía - - Iniciante - - JavaScript -translation_of: Web/JavaScript/Guide/Grammar_and_types ---- -

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}

- -

Este capítulo trata sobre a sintaxe básica do JavaScript, declarações de variáveis, tipos de dados e literais.

- -

Sintaxe básica

- -

JavaScript pega emprestado a maior parte de sua sintaxe do Java, mas também é influenciado por Awk, Perl e Python.

- -

JavaScript é case-sensitive e usa o conjunto de caracteres Unicode. Por exemplo, a palavra Früh (que significa "cedo" em Alemão) pode ser usada como nome de variável.

- -
var Früh = "foobar";
- -

Mas a variável früh não é a mesma que Früh porque JavaScript é case sensitive.

- -

No JavaScript, instruções são chamadas de {{Glossary("Statement", "declaração")}} e são separadas por um ponto e vírgula (;). Espaços, tabulação e uma nova linha são chamados de espaços em branco. O código fonte dos scripts em JavaScript são lidos da esquerda para a direita e são convertidos em uma sequência de elementos de entrada como simbolos, caracteres de controle, terminadores de linha, comentários ou espaço em branco. ECMAScript também define determinadas palavras-chave e literais, e tem regras para inserção automática de ponto e vírgula (ASI) para terminar as declarações. No entanto, recomenda-se sempre adicionar ponto e vírgula no final de suas declarações; isso evitará alguns imprevistos. Para obter mais informações, consulte a referência detalhada sobre a gramática léxica do JavaScript.

- -

Comentários

- -

A sintaxe dos comentários em JavaScript é semelhante como em C++ e em muitas outras linguagens:

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

Declarações

- -

Existem três tipos de declarações em JavaScript.

- -
-
{{jsxref("Statements/var", "var")}}
-
Declara uma variável, opcionalmente, inicializando-a com um valor.
-
{{experimental_inline}} {{jsxref("Statements/let", "let")}}
-
Declara uma variável local de escopo do bloco, opcionalmente, inicializando-a com um valor.
-
{{experimental_inline}} {{jsxref("Statements/const", "const")}}
-
Declara uma constante de escopo de bloco, apenas de leitura.
-
- -

Variáveis

- -

Você usa variáveis como nomes simbólicos para os valores em sua aplicação. O nome das variáveis, chamados de {{Glossary("Identifier", "identificadores")}}, obedecem determinadas regras.

- -

Um identificador JavaScript deve começar com uma letra, underline (_), ou cifrão ($); os caracteres subsequentes podem também ser números (0-9). Devido JavaScript ser case-sensitive, letras incluem caracteres de "A" a "Z" (maiúsculos) e caracteres de "a" a "z" (minúsculos).

- -

Você pode usar a ISO 8859-1 ou caracteres Unicode tal como os identificadores å e ü. Você pode também usar as sequências de escape Unicode como caracteres e identificadores.

- -

Alguns exemplos de nomes legais são Numeros_visitas, temp99, e _nome.

- -

Declarando variáveis

- -

Você pode declarar uma variável de três formas:

- - - -

Classificando variáveis

- -

Uma variável declarada usando a declaração var ou let sem especificar o valor inicial tem o valor  {{jsxref("undefined")}}.

- -

Uma tentativa de acessar uma variável não declarada resultará no lançamento de uma exceção {{jsxref("ReferenceError")}}:

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

Você pode usar undefined para determinar se uma variável tem um valor. No código a seguir, não é atribuído um valor de entrada na variável e a declaração if será avaliada como verdadeira (true).

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

O valor undefined se comporta como falso (false), quando usado em um contexto booleano. Por exemplo, o código a seguir executa a função myFunction devido o elemento myArray ser undefined:

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

O valor undefined converte-se para NaN quando usado no contexto numérico.

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

Quando você avalia uma variável nula, o valor nulo se comporta como 0 em contextos numéricos e como falso em contextos booleanos. Por exemplo:

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

Escopo de variável

- -

Quando você declara uma váriavel fora de qualquer função, ela é chamada de variável global, porque está disponível para qualquer outro código no documento atual. Quando você declara uma variável dentro de uma função, é chamada de variável local,  pois ela está disponível somente dentro dessa função.

- -

JavaScript antes do ECMAScript 6 não possuía escopo de declaração de bloco; pelo contrário, uma variável declarada dentro de um bloco de uma função é uma variável local (ou contexto global) do bloco que está inserido a função. Por exemplo o código a seguir exibirá 5, porque o escopo de x está na função (ou contexto global) no qual x é declarado, não o bloco, que neste caso é a declaração if

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

Esse comportamento é alterado, quando usado a declaração let introduzida pelo ECMAScript 6.

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

Variável de elevação

- -

Outra coisa incomum sobre variáveis em JavaScript é que você pode utilizar a variável e declará-la depois, sem obter uma exceção. Este conceito é conhecido como hoisting; variáveis em JavaScript são num sentido "hoisted" ou lançada para o topo da função ou declaração. No entanto, as variáveis que são "hoisted" retornarão um valor undefined. Então, mesmo se você usar ou referir a variável e depois declará-la e inicializá-la, ela ainda retornará undefined.

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

Os exemplos acima serão interpretados como:

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

Devido o hoisting, todas as declarações var em uma função devem ser colocadas no início da função. Essa recomendação de prática deixa o código mais legível.

- -

Variáveis Globais

- -

Variáveis globais são propriedades do objeto global. Em páginas web o objeto global é a {{domxref("window")}}, assim você pode configurar e acessar variáveis globais utilizando a sintaxe window.variavel. 

- -

Consequentemente, você pode acessar variáveis globais declaradas em uma janela ou frame ou frame de outra janela. Por exemplo, se uma variável chamada phoneNumber é declarada em um documento, você pode consultar esta variável de um frame como parent.phoneNumber.

- -

Constantes

- -

Você pode criar uma constante apenas de leitura por meio da palavra-chave {{jsxref("Statements/const", "const")}}. A sintaxe de um identificador de uma constante é semelhante ao identificador de uma variável: deve começar com uma letra, sublinhado ou cifrão e pode conter caractere alfabético, numérico ou sublinhado.

- -
const PI = 3.14;
-
- -

Uma constante não pode alterar seu valor por meio de uma atribuição ou ser declarada novamente enquanto o script está em execução. Deve ser inicializada com um valor.

- -

As regras de escopo para as constantes são as mesmas para as váriaveis let de escopo de bloco. Se a palavra-chave const for omitida, presume-se que o identificador represente uma variável.

- -

Você não pode declarar uma constante com o mesmo nome de uma função ou variável que estão no mesmo escopo. Por exemplo: 

- -
// Isto irá causar um  erro
-function f() {};
-const f = 5;
-
-// Isto também irá causar um erro.
-function f() {
-  const g = 5;
-  var g;
-
-  //declarações
-}
-
- -

Estrutura de dados e tipos

- -

Tipos de dados

- -

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

- - - -

Embora esses tipos de dados sejam uma quantidade relativamente pequena, eles permitem realizar funções úteis em suas aplicações.  {{jsxref("Object", "Objetos")}} e {{jsxref("Function", "funções")}} são outros elementos fundamentais na linguagem. Você pode pensar em objetos como recipientes para os valores, e funções como métodos que suas aplicações podem executar.

- -

Conversão de tipos de dados

- -

JavaScript é uma linguagem dinamicamente tipada. Isso significa que você não precisa especificar o tipo de dado de uma variável quando declará-la, e tipos de dados são convertidos automaticamente conforme a necessidade durante a execução do script. Então, por exemplo, você pode definir uma variável da seguinte forma:

- -
var answer = 42;
-
- -

E depois, você pode atribuir uma string para a mesma variável, por exemplo:

- -
answer = "Obrigado pelos peixes...";
-
- -

Devido JavaScript ser dinamicamente tipado, essa declaração não gera uma mensagem de erro.

- -

Em expressões envolvendo valores numérico e string com o operador +, JavaScript converte valores numérico para strings. Por exemplo, considere a seguinte declaração:

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

Nas declarações envolvendo outros operadores,  JavaScript não converte valores numérico para strings. Por exemplo:

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

Convertendo strings para números

- -

No caso de um valor que representa um número está armazenado na memória como uma string, existem métodos para a conversão.

- - - -

parseInt irá retornar apenas números inteiros, então seu uso é restrito para a casa dos decimais. Além disso, é uma boa prática ao usar parseInt incluir o parâmetro da base. O parâmetro da base é usado para especificar qual sistema númerico deve ser usado.

- -

Uma método alternativo de conversão de um número em forma de string é com o operador + (operador soma):

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

Literais

- -

Você usa literais para representar valores em JavaScript. Estes são valores fixados, não variáveis, que você literalmente insere em seu script. Esta seção descreve os seguintes tipos literais:

- - - -

Array literal

- -

Um array literal é uma lista de zero ou mais expressões, onde cada uma delas representam um elemento do array, inseridas entre colchetes ([]). Quando você cria um array usando um array literal, ele é inicializado  com os valores especificados como seus elementos, e seu comprimento é definido com o  número de elementos especificados.

- -

O exemplo a seguir cria um array coffees com três elementos e um comprimento de três:

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

Nota : Um array literal é um tipo de inicializador de objetos. Veja Usando inicializadores de Objetos.

-
- -

Se um array é criado usando um literal no topo do script, JavaScript interpreta o array cada vez que avalia a expressão que contêm o array literal. Além disso, um literal usado em uma função é criado cada vez que a função é chamada.

- -

Array literal são também um array de objetos. Veja  {{jsxref("Array")}} e Coleções indexadas para detalhes sobre array de objetos.

- -

Vírgulas extras em array literal

- -

Você não precisa especificar todos os elementos em um array literal. Se você colocar duas vírgulas em uma linha, o array é criado com undefined para os elementos não especificados. O exemplo a seguir cria um array chamado fish:

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

Esse array tem dois elementos com valores e um elemento vazio (fish[0] é "Lion", fish[1] é undefined, e fish[2] é "Angel" ).

- -

Se você incluir uma vírgula à direita no final da lista dos elementos, a vírgula é ignorada. No exemplo a seguir, o comprimento do array é três. Não há nenhum myList[3]. Todas as outras vírgulas na lista indicam um novo elemento.

- -
-

Nota : Vírgulas à direita podem criar erros em algumas versões de navegadores web antigos, é recomendável removê-las.

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

No exemplo a seguir, o comprimento do array é quatro, e myList[0] e myList[2] são undefined.

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

No exemplo a seguir, o comprimento do array é quatro, e myList[1] e myList[3] são undefined. Apenas a última vírgula é ignorada.

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

Entender o comportamento de vírgulas extras é importante para a compreensão da linguagem JavaScript, no entanto, quando você escrever seu próprio código: declarar explicitamente os elementos em falta como undefined vai aumentar a clareza do código, e consequentemente na sua manutenção.

- -

Literais Boolean

- -

O tipo Boolean tem dois valores literal: true e false.

- -

Não confunda os valores primitivos Boolean true e false com os valores true e false do objeto Boolean. O objeto Boolean é um invólucro em torno do tipo de dado primitivo. Veja {{jsxref("Boolean")}} para mais informação.

- -

Inteiros

- -

Inteiros podem ser expressos em decimal (base 10), hexadecimal (base 16), octal (base 8) e binário (base 2).

- - - -

Alguns exemplos de inteiros literal são:

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

Para maiores informações, veja Literais numérico na referência Léxica.

- -

Literais de ponto flutuante

- -

Um literal de ponto flutuante pode ter as seguintes partes:

- - - -

O expoente é um "e" ou "E" seguido por um inteiro, que pode ter sinal (precedido por "+" ou "-"). Um literal de ponto flutuante  deve ter no mínimo um dígito e um ponto decimal ou "e" (ou "E").

- -

Mais sucintamente, a sintaxe é:

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

Por exemplo:

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

Objeto literal

- -

Um objeto literal é uma lista de zero ou mais pares de nomes de propriedades e valores associados de um objeto, colocado entre chaves ({}). Você não deve usar um objeto literal no início de uma declaração. Isso levará a um erro ou não se comportará conforme o esperado, porque o { será interpretado como início de um bloco.

- -

Segue um exemplo de um objeto literal. O primeiro elemento do objeto carro define uma propriedade, meuCarro, e atribui para ele uma nova string, "Punto"; o segundo elemento, a propriedade getCarro, é imediatamente atribuído o resultado de chamar uma função (tipoCarro("Fiat")); o terceiro elemento, a propriedade especial, usa uma variável existente (vendas).

- -
var vendas = "Toyota";
-
-function tipoCarro(nome) {
-  if (nome == "Fiat") {
-    return nome;
-  } else {
-    return "Desculpa, não vendemos carros " + nome + ".";
-  }
-}
-
-var carro = { meuCarro: "Punto", getCarro: tipoCarro("Fiat"), especial: vendas };
-
-console.log(carro.meuCarro);   // Punto
-console.log(carro.getCarro);  // Fiat
-console.log(carro.especial); // Toyota
-
- -

Além disso, você pode usar um literal numérico ou string para o nome de uma propriedade ou aninhar um objeto dentro do outro. O exemplo a seguir usar essas opções.

- -
var carro = { carros: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };
-
-console.log(carro.carros.b); // Jeep
-console.log(carro[7]); // Mazda
-
- -

Nomes de propriedades de objeto podem ser qualquer string, incluindo uma string vazia. Caso o nome da propriedade não seja um {{Glossary("Identifier","identificador")}} JavaScript ou número, ele deve ser colocado entre aspas. Nomes de propriedades que não possuem identificadores válido, também não podem ser acessadas pela propriedade de ponto (.), mas podem ser acessadas e definidas com a notação do tipo array ("[]").

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

Observe:

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

 

- -

Expressão Regex Literal

- -

Um regex literal é um padrão entre barras. A seguir um exemplo de regex literal.

- -
var re = /ab+c/;
- -

String Literal

- -

Uma string literal são zero ou mais caracteres dispostos em aspas duplas (") ou aspas simples ('). Uma sequência de caracteres deve ser delimitada por aspas do mesmo tipo; ou seja,  as duas aspas simples ou ambas aspas duplas. A seguir um exemplo de strings literais.

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

Você pode chamar qualquer um dos métodos do objeto string em uma string literal - JavaScript automaticamente converte a string literal para um objeto string temporário, chama o método, em seguida, descarta o objeto string temporário. Você também pode usar a propriedade String.length com uma string literal:

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

Você deve usar string literal, a não ser que você precise usar um objeto string. Veja {{jsxref("String")}} para detalhes sobre objetos de strings.

- -

Uso de caracteres especiais em string

- -

Além dos caracteres comuns, você também pode incluir caracteres especiais em strings, como mostrado no exemplo a seguir.

- -
"uma linha \n outra linha"
-
- -

A tabela a seguir lista os caracteres especiais que podem ser usados em strings no JavaScript.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tabela: Caracteres especiais no JavaScript
CaracterDescrição
\0Byte nulo
\bBackspace
\fAlimentador de formulário
\nNova linha
\rRetorno do carro
\tTabulação
\vTabulação vertical
\'Apóstrofo ou aspas simples
\"Aspas dupla
\\Caractere de barra invertida
\XXX -

Caractere com a codificação Latin-1 especificada por três dígitos octal XXX entre 0 e 377. Por exemplo, \251 é sequência octal para o símbolo de direitos autorais.

-
\xXX -

Caractere com a codificação Latin-1 especificada por dois dígitos hexadecimal XX entre 00 e FF. Por exemplo, \xA9 é a sequência hexadecimal para o símbolo de direitos autorais.

-
\uXXXX -

Caractere Unicode especificado por quatro dígitos hexadecimal XXXX. Por exemplo, \u00A9 é a sequência Unicode para o símbolo de direitos autorais. Veja sequências de escape Unicode.

-
- -

Caracteres de escape

- -

Para caracteres não listados na tabela, se precedidos de barra invertida ela é ignorada, seu uso está absoleto e deve ser ignorado.

- -

Você pode inserir uma aspa dentro de uma string precendendo-a com uma barra invertida. Isso  é conhecido como escaping das aspas. Por exemplo:

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

O resultado disso seria:

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

Para incluir uma barra invertida dentro de uma string, você deve escapar o caractere de barra invertida. Por exemplo, para atribuir o caminho do arquivo c:\temp para uma string, utilize o seguinte:

- -
var home = "c:\\temp";
-
- -

Você também pode escapar quebras de linhas, precedendo-as com barra invertida. A barra invertida e a quebra de linha são ambas removidas da string.

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

Embora JavaScript não tenha sintaxe "heredoc", você pode adicionar uma quebra de linha e um escape de quebra de linha no final de cada linha:

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

Mais informação

- -

Este capítulo focou na sintaxe básica das declarações e tipos. Para saber mais sobre a linguagem JavaScript, veja também os seguintes capítulos deste guia:

- - - -

No próximo capítulo, veremos a construção de controle de fluxos e manipulação de erro.

- -

{{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}

diff --git a/files/pt-br/web/javascript/guide/working_with_objects/index.html b/files/pt-br/web/javascript/guide/working_with_objects/index.html new file mode 100644 index 0000000000..1dccaeef2e --- /dev/null +++ b/files/pt-br/web/javascript/guide/working_with_objects/index.html @@ -0,0 +1,494 @@ +--- +title: Trabalhando com objetos +slug: Web/JavaScript/Guide/Trabalhando_com_Objetos +tags: + - Comparando Objetos + - Contrutor + - Documento + - ECMAScript6 + - Guia(2) + - Iniciante + - JavaScript +translation_of: Web/JavaScript/Guide/Working_with_Objects +--- +

A linguagem JavaScript é projetada com base em um simples paradigma orientado a objeto. Um objeto é uma coleção de propriedades, e uma propriedade é uma associação entre um nome (ou chave) e um valor. Um valor de propriedade pode ser uma função, que é então considerada um método do objeto. Além dos objetos que são pré-definidos no browser, você pode definir seus próprios objetos.

+ +

Este capítulo descreve como usar objetos, propriedades, funções, e métodos, e como criar seus próprios objetos.

+ +

Visão geral de objetos

+ +

Objetos em JavaScript, assim como em muitas outras linguagens de programação, podem ser comparados com objetos na vida real. O conceito de objetos em JavaScript pode ser entendido com objetos tangíveis da vida real.

+ +

Em JavaScript, um objeto é uma entidade independente, com propriedades e tipos. Compare-o com uma xícara, por exemplo. Uma xícara é um objeto, com propriedades. Uma xícara tem uma cor, uma forma, peso, um material de composição, etc. Da mesma forma, objetos em JavaScript podem ter propriedades, que definem suas características.

+ +

Objetos e propriedades

+ +

Um objeto em JavaScript tem propriedades associadas a ele. Uma propriedade de um objeto pode ser explicada como uma variável que é ligada ao objeto. Propriedades de objetos são basicamente as mesmas que variáveis normais em JavaScript, exceto pelo fato de estarem ligadas a objetos. As propriedades de um objeto definem as características do objeto. Você acessa as propriedades de um objeto com uma simples notação de ponto:

+ +
+
nomeDoObjeto.nomeDaPropriedade
+
+
+ +

Como as variáveis em JavaScript, o nome do objeto (que poderia ser uma variável normal) e um nome de propriedade diferem em maiúsculas/minúsculas (por exemplo, cor e Cor são propriedades diferentes). Você pode definir uma propriedade atribuindo um valor a ela. Por exemplo, vamos criar um objeto chamado meuCarro e dar a ele propriedades chamadas fabricacao, modelo, e ano, conforme mostrado a seguir:

+ +
var meuCarro = new Object();
+meuCarro.fabricacao = "Ford";
+meuCarro.modelo = "Mustang";
+meuCarro.ano = 1969;
+
+ +

Propriedades não definidas de um objeto são {{jsxref("undefined")}} (e não {{jsxref("null")}}).

+ +
meuCarro.semPropriedade; //undefined
+ +

Propriedades de objetos em JavaScript podem também ser acessadas ou alteradas usando-se notação de colchetes. Objetos são às vezes chamados de arrays associativos, uma vez que cada propriedade é associada com um valor de string que pode ser usado para acessá-la. Então, por exemplo, você poderia acessar as propriedades do objeto meuCarro como se segue:

+ +
meuCarro["fabricacao"] = "Ford";
+meuCarro["modelo"] = "Mustang";
+meuCarro["ano"] = 1969;
+
+ +

Um nome de propriedade de um objeto pode ser qualquer string JavaScript válida, ou qualquer coisa que possa ser convertida em uma string, incluindo uma string vazia. No entanto, qualquer nome e propriedade que não é um identificador JavaScript válido (por exemplo, um nome de propriedade que tem um espaço ou um hífen, ou que começa com um número) só pode ser acessado(a) usando-se a notação de colchetes. Essa notação é também muito útil quando nomes de propriedades devem ser determinados dinamicamente (quando o nome da propriedade não é determinado até o momento de execução). Exemplos são mostrados a seguir:

+ +
var meuObj = new Object(),
+    str = "minhaString",
+    aleat = Math.random(),
+    obj = new Object();
+
+meuObj.tipo               = "Sintaxe de ponto";
+meuObj["data de criacao"] = "String com espaco";
+meuObj[str]               = "valor de String";
+meuObj[aleat]             = "Numero Aleatorio";
+meuObj[obj]               = "Objeto";
+meuObj[""]                = "Mesmo uma string vazia";
+
+console.log(meuObj);
+
+ +

Você pode também acessar propriedades usando um valor de string que está armazenado em uma variável:

+ +
+
var nomeDaPropriedade = "fabricacao";
+meuCarro[nomeDaPropriedade] = "Ford";
+
+nomeDaPropriedade = "modelo";
+meuCarro[nomeDaPropriedade] = "Mustang";
+
+
+ +

Você pode usar a notação de colchetes com o comando for...in para iterar por todas as propriedades enumeráveis de um objeto. Para ilustrar como isso funciona, a seguinte função mostra as propriedades de um objeto quando você passa o objeto e o nome do objeto como argumentos para a função:

+ +
function mostrarProps(obj, nomeDoObj) {
+  var resultado = "";
+  for (var i in obj) {
+    if (obj.hasOwnProperty(i)) {
+        resultado += nomeDoObj + "." + i + " = " + obj[i] + "\n";
+    }
+  }
+  return resultado;
+}
+
+ +

Então, a chamada de função mostrarProps(meuCarro, "meuCarro") retornaria o seguinte:

+ +
meuCarro.fabricacao = Ford
+meuCarro.modelo = Mustang
+meuCarro.ano = 1969
+ +

Objetos: tudo

+ +

Em JavaScript, quase tudo é um objeto. Todos os tipos primitivos - com exceção de null e undefined - são tratados como objetos. Eles podem receber propriedades (propriedades atribuídas de alguns tipos não são persistentes), e possuem todas as características de objetos.

+ +

Enumerando todas as propriedades de um objeto

+ +

Começando com a ECMAScript 5, há três formas nativas de se listar (ou "caminhar por") as propriedades de um objeto:

+ + + +

Antes, na ECMAScript 5, não existia uma forma nativa de se listar todas as propriedades de um objeto. No entanto, isso pode ser feito com a seguinte função:

+ +
function listarTodasAsPropriedades(o){
+	var objectoASerInspecionado;
+	var resultado = [];
+
+	for(objectoASerInspecionado = o; objectoASerInspecionado !== null; objectoASerInspecionado = Object.getPrototypeOf(objectoASerInspecionado)){
+		resultado = resultado.concat(Object.getOwnPropertyNames(objectoASerInspecionado));
+	}
+
+	return resultado;
+}
+
+ +

Isso pode ser útil para revelar propriedades "escondidadas" (propriedades na cadeia de protótipos que não são acessíveis através do objeto, porque outra propriedade possui o mesmo nome anteriormente na cadeia de protótipos). A listagem de propriedades acessíveis só pode ser facilmente feita através da remoção de valores duplicados no array.

+ +

Criando novos objetos

+ +

JavaScript possui um número de objetos pré-definidos. Além disso, você pode criar seus próprios objetos. Você pode criar um objeto usando um objeto inicializador. Alternativamente, você pode primeiro criar uma função construtora e depois instanciar um objeto usando aquela função e o operador new.

+ +

Usando inicializadores de objeto

+ +

Além de criar objetos usando uma função construtora, você pode criar objetos usando um inicializador de objeto. O uso de inicializadores de objeto é às vezes conhecido como criar objetos com notação literal. O termo "inicializador de objeto" é consistente com a terminologia usada por C++.

+ +

A sintaxe para um objeto usando-se um inicializador de objeto é:

+ +
var obj = { propriedade_1:   valor_1,   // propriedade_# pode ser um identificador...
+            2:            valor_2,   // ou um numero...
+            // ...,
+            "propriedade n": valor_n }; // ou uma string
+
+ +

onde obj é o nome do novo objeto, cada propriedade_i é um identificador (um nome, um número, ou uma string literal), e cada valor_i é uma expressão cujo valor é atribuído à propriedade_i. O obj e a atribuição são opcionais; se você não precisa fazer referência a esse objeto em nenhum outro local, você não precisa atribuí-lo a uma variável. (Note que você pode precisar colocar o objeto literal entre parentêses se o objeto aparece onde um comando é esperado, de modo a não confundir o literal com uma declaração de bloco.)

+ +

Se um objeto é criado com um inicializador de objeto em um script de alto nível, JavaScript interpreta o objeto a cada vez que avalia uma expressão contendo o objeto literal. Além disso, um inicializador usado em uma função é criado toda vez que a função é chamada.

+ +

O seguinte comando cria um objeto e o atribui à variável x somente se a expressão cond é verdadeira.

+ +
if (cond) var x = {hi: "there"};
+
+ +

O seguinte exemplo cria minhaHonda com três propriedades. Note que a propriedade motor é também um objeto com suas próprias propriedades.

+ +
var minhaHonda = {cor: "vermelho", rodas: 4, motor: {cilindros: 4, tamanho: 2.2}};
+
+ +

Você pode também usar inicializadores de objeto para criar arrays. Veja arrays literais.

+ +

Usando uma função construtora

+ +

Alternativamente, você pode criar um objeto com estes dois passos:

+ +
    +
  1. Defina o tipo de objeto escrevendo uma função construtora. Há uma forte convenção, e com boa razão, de se usar uma letra inicial maiúscula.
  2. +
  3. Crie uma instância do objeto com new.
  4. +
+ +

Para definir um tipo de objeto, crie uma função para o tipo de objeto que especifique seu nome, suas propriedades e seus métodos. Por exemplo, suponha que você queira criar um tipo objeto para carros. Você quer que esse tipo de objeto seja chamado carro, e você quer ele tenha propriedades de marca, modelo, e ano. Para fazer isto, você escreveria a seguinte função:

+ +
function Carro(marca, modelo, ano) {
+  this.marca = marca;
+  this.modelo = modelo;
+  this.ano = ano;
+}
+
+ +

Note o uso de this para atribuir valores às propriedades do objeto com base nos valores passados para a função.

+ +

Agora você pode criar um objeto chamado meucarro como se segue:

+ +
var meucarro = new Carro("Eagle", "Talon TSi", 1993);
+
+ +

Esse comando cria meucarro e atribui a ele valores especificados para suas propriedade. Então o valor de meucarro.marca é a string "Eagle", meucarro.ano é o inteiro 1993, e assim por diante.

+ +

Você pode criar qualquer número de objetos carro com o uso de new. Exemplo,

+ +
var carroDeKen = new Carro("Nissan", "300ZX", 1992);
+var carroDeVPG = new Carro("Mazda", "Miata", 1990);
+
+ +

Um objeto pode ter uma propriedade que por si só também é um objeto. Por exemplo, suponha que você define um objeto chamado pessoa como se segue:

+ +
function Pessoa(nome, idade, sexo) {
+  this.nome = nome;
+  this.idade = idade;
+  this.sexo = sexo;
+}
+
+ +

e então você instancia dois novos objetos pessoa da seguinte forma:

+ +
var jose = new Pessoa("Jose Silva", 33, "M");
+var paulo = new Pessoa("Paulo Santos", 39, "M");
+
+ +

Então, você pode reescrever a definição de carro de modo a incluir uma propriedade dono que recebe um objeto pessoa, como se segue:

+ +
function Carro(marca, modelo, ano, dono) {
+  this.marca = marca;
+  this.modelo = modelo;
+  this.ano = ano;
+  this.dono = dono;
+}
+
+ +

Para instanciar os novos objetos, você então usa o seguinte:

+ +
var carro1 = new Carro("Eagle", "Talon TSi", 1993, jose);
+var carro2 = new Carro("Nissan", "300ZX", 1992, paulo);
+
+ +

Perceba que ao invés de passar uma string literal ou um valor inteiro na hora de criar os novos objetos, os comandos acima passam os objetos jose e paulo como os argumentos para os donos. Então se você quiser descobrir o nome do dono de carro2, você pode acessar a seguinte propriedade:

+ +
carro2.dono
+
+ +

Note que você pode sempre adicionar uma propriedade a um objeto definido anteriormente. Por exemplo, o comando

+ +
carro1.cor = "preto";
+
+ +

adiciona uma propriedade cor ao carro1, e dá a ele o valor "preto." No entanto, isso não afeta nenhum outro objeto. Para adicionar a nova propriedade a todos os objetos do mesmo tipo, você deve adicionar a propriedade na definição do tipo de objeto carro.

+ +

Usando o método Object.create

+ +

Objetos podem também ser criados usando-se o método Object.create(). Esse método pode ser muito útil, pois permite que você escolha o objeto protótipo para o objeto que você quer criar, sem a necessidade de se definir uma função construtora.

+ +
// Encapsulamento das propriedades e métodos de Animal
+var Animal = {
+  tipo: "Invertebrados", // Propriedades de valores padrão
+  qualTipo : function() {  // Método que ira mostrar o tipo de Animal
+    console.log(this.tipo);
+  }
+}
+
+// Cria um novo tipo de animal chamado animal1
+var animal1 = Object.create(Animal);
+animal1.qualTipo(); // Saída:Invertebrados
+
+// Cria um novo tipo de animal chamado Peixes
+var peixe = Object.create(Animal);
+peixe.tipo = "Peixes";
+peixe.qualTipo(); // Saída: Peixes
+ +

Herança

+ +

Todos os objetos em JavaScript herdam de pelo menos um outro objeto. O objeto "pai" é conhecido como o protótipo, e as propriedades herdadas podem ser encontradas no objeto prototype do construtor.

+ +

Indexando Propriedades de Objetos

+ +

Você pode se referir a uma propriedade de um objeto pelo seu nome de propriedade ou pelo seu índice ordinal. Se você inicialmente definiu uma propriedade pelo nome, você deve sempre se referir a ela pelo nome, e se você inicialmente definir uma propriedade por um índice, você deve sempre se referir a ela pelo índice.

+ +

Esta restrição se aplica quando  você cria um objeto e suas propriedades com uma função construtora (como fizemos anteriormente com o objeto do tipo carro) e quando você define propriedades individuais explicitamente (por exemplo, meuCarro.cor = "vermelho"). Se você inicialmente definir uma propriedade do objeto com um índice, tal como meuCarro[5] = "25 mpg", você pode subsequentemente referir-se á propriedade somente como meuCarro[5].

+ +

A exceção a esta regra é a objetos refletidos a partir do HTML, como o conjunto de formulários. Você pode sempre se referir a objetos nessas matrizes por seu número de ordem (com base em onde eles aparecem no documento) ou seu nome (se definido). Por exemplo, se a segunda tag <FORM> em um  documento tem um atributo NAME de "meuFormulario", você pode se referir ao formulário como document.forms[1] ou document.forms["meuFormulario"] ou document.meuFormulario.

+ +

Definindo propriedades para um tipo de objeto

+ +

Você pode adicionar uma propriedade a um tipo de objeto definido anteriormente, utilizando a propriedade prototype. Esta define uma propriedade que é partilhada por todos os objetos do tipo especificado, em vez de apenas uma instância do objeto. O código a seguir adiciona uma propriedade cor para todos os objetos do tipo Carro, em seguida adiciona um valor a propriedade cor do objeto carro1.

+ +
Carro.prototype.cor = null;
+carro1.cor = "preto";
+
+ +

Consulte a propriedade prototype do objeto Function na Referência JavaScript  para mais informações.

+ +

Definindo métodos

+ +

Um método é uma função associada a um objeto, ou, simplesmente, um método é uma propriedade de um objeto que é uma função. Métodos são definidos da forma que as funções normais são definidas, exceto que eles tenham que ser atribuídos como propriedade de um objeto. São exemplos:

+ +
nomeDoObjeto.nomedometodo = nome_da_funcao;
+
+var meuObjeto = {
+  meuMetodo: function(parametros) {
+    // ...faça algo
+  }
+};
+
+ +

Onde nomeDoObjeto é um objeto existente, nomedometodo é o nome que você atribuiu ao método, e nome_da_funcao é o nome da função.

+ +

Em seguida, você pode chamar o método no contexto do objeto da seguinte forma:

+ +
objeto.nomedometodo(parametros);
+
+ +

Você pode definir métodos para um tipo de objeto incluindo uma definição de metodo na função construtora do objeto. Por exemplo, você poderia definir uma função que iria formatar e mostrar as propriedades do objeto carro previamente definido; por exemplo,

+ +
function mostreCarro() {
+  var resultado = "Um belo " + this.ano + " " + this.fabricacao
+    + " " + this.modelo;
+  pretty_print(resultado);
+}
+
+ +

onde pretty_print é uma função que mostra uma linha horizontal e uma string. Observe o uso de this para referenciar o objeto ao qual o método pertence.

+ +

Você pode fazer desta função um método de carro, adicionando seu estado à definição do objeto.

+ +
this.mostreCarro = mostreCarro;
+
+ +

Assim, a definição completa de carro seria agora, parecida com essa:

+ +
function Carro(fabricacao, modelo, ano, proprietario) {
+  this.fabricacao = fabricacao;
+  this.modelo = modelo;
+  this.ano = ano;
+  this.proprietario = proprietario;
+  this.mostreCarro = mostreCarro;
+}
+
+ +

Então você pode chamar o método mostreCarro para cada objeto seguinte:

+ +
carro1.mostreCarro();
+carro2.mostreCarro();
+
+ +

Usando this para referências de objetos

+ +

JavaScript tem uma palavra-chave especial, this, que você pode usar dentro de um método para referenciar o objeto corrente. Por exemplo, suponha que você tenha uma função chamada validate que valida o valor da propriedade de um objeto, dado o objeto e os valores altos e baixos:

+ +
function validate(obj, lowval, hival) {
+  if ((obj.value < lowval) || (obj.value > hival))
+    alert("Valor inválido!");
+}
+
+ +

Então, você poderia chamar validate no manipulador de evento onchange em cada elemento do formulário, usando this para passar o elemento, como no exemplo a seguir:

+ +
<input type="text" name="age" size="3"
+  onChange="validate(this, 18, 99)">
+
+ +

No geral, this referencia o objeto chamando um método.

+ +

Quando combinado com a propriedade form , this pode referenciar a forma original do objeto atual. No exemplo seguinte, o formulário myForm contém um objeto Text e um botão. Quando o usuário clica no botão, o valor do objeto Text é definido como nome do formulário. O manipulador de eventos onclick do botão usa this.form para referenciar a forma original, myForm.

+ +
<form name="myForm">
+<p><label>Nome do form:<input type="text" name="text1" value="Beluga"></label>
+<p><input name="button1" type="button" value="Mostre o Nome do Form"
+     onclick="this.form.text1.value = this.form.name">
+</p>
+</form>
+ +

Definindo getters e setters

+ +

Um getter é um método que obtém o valor de uma propriedade específica. Um setter é um método que define o valor de uma propriedade específica. Você pode definir getters e setters em qualquer objeto de núcleo pré-definido ou objeto definido pelo usuário que suporta a adição de novas propriedades. A sintaxe para definir getters e setters usa a sintaxe literal do objeto.

+ +

O código a seguir ilustra como getters e setters podem funcionar para um objeto o definido pelo usuário.

+ +
var o = {
+  a: 7,
+  get b() {
+    return this.a + 1;
+  },
+  set c(x) {
+    this.a = x / 2
+  }
+};
+
+console.log(o.a); // 7
+console.log(o.b); // 8
+o.c = 50;
+console.log(o.a); // 25
+ +

As propriedades do objeto o são:

+ + + +

Observe que nomes de função de getters e setters definidos em um objeto literal usando "[gs]et property()" (ao contrário de __define[GS]etter__ ) não são os próprios nomes dos getters, embora a sintaxe [gs]et propertyName(){ } possa  induzir ao erro e você pensar de outra forma. Para nomear uma função getter ou setter usando a sintaxe "[gs]et property()", define explicitamente um função nomeada programaticamente usando Object.defineProperty (ou o legado fallback Object.prototype.__defineGetter__).

+ +

O código a seguir ilustra como getters e setters podem extender o protótipo Date para adicionar a propriedade ano para todas as instâncias de classes Date pré-definidas. Ele usa os métodos getFullYear e setFullYear existentes da classe Date para suportar o getter e setter da propriedade ano.

+ +

Estes estados definem um getter e setter para a propriedade ano:

+ +
var d = Date.prototype;
+Object.defineProperty(d, "year", {
+  get: function() { return this.getFullYear() },
+  set: function(y) { this.setFullYear(y) }
+});
+ +

Estes estados usam o getter e setter em um objeto Date:

+ +
var now = new Date();
+console.log(now.year); // 2000
+now.year = 2001; // 987617605170
+console.log(now);
+// Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
+ +

A principio, getters e setters podem ser ou

+ + + +

Ao definir getters e setters usando objetos inicializadores tudo o que você precisa fazer é prefixar um método getter com get e um método setter com set. Claro, o método getter não deve esperar um parâmetro, enquanto o método setter espera exatamente um parâmetro (novo valor para definir). Por exemplo:

+ +
var o = {
+  a: 7,
+  get b() { return this.a + 1; },
+  set c(x) { this.a = x / 2; }
+};
+
+ +

Getters e setters podem também ser adicionado em um objeto a qualquer hora depois da criação usando o método Object.defineProperties. O primeiro parâmetro deste método é o objeto no qual você quer definir o getter ou setter. O segundo parâmetro é um objeto cujos nomes das propriedades são os nomes getter ou setter, e cujo valores das propriedades são objetos para definição de funções getter ou setter. Aqui está um exemplo que define o mesmo getter e setter usado no exemplo anterior:
+  

+ +
var o = { a:0 }
+
+Object.defineProperties(o, {
+    "b": { get: function () { return this.a + 1; } },
+    "c": { set: function (x) { this.a = x / 2; } }
+});
+
+o.c = 10 // Roda o setter, que associa 10 / 2 (5) para a propriedade 'a'
+console.log(o.b) // Roda o getter, que yields a + 1 ou 6
+
+ +

Escolher qual das duas formas depende do seu estilo de programação e tarefa na mão. Se você já vai para o inicializador de objeto ao definir um protótipo, provavelmente a maior parte do tempo escolherá a primeira forma. Esta forma é mais compacta e natural. No entanto, se você precisar adicionar getters e setters mais tarde - porque você não escreveu o protótipo ou objeto particular - então a segunda forma é a única possível. A segunda forma provavelmente melhor representa a natureza dinâmica do JavaScript - mas pode tornar o código difícil de ler e entender.

+ +

Removendo propriedades

+ +

Você pode remover uma propriedade não herdada usando o operador delete. O código a seguir mostra como remover uma propriedade.

+ +
//Criando um novo objeto, myobj, com duas propriedades, a e b.
+var myobj = new Object;
+myobj.a = 5;
+myobj.b = 12;
+
+//Removendo a propriedade a, deixando myobj com apenas a propriedade b.
+delete myobj.a;
+console.log ("a" in myobj) // yields "false"
+
+ +

Você também pode usar delete para remover uma variável global se a var keyword não estiver sendo usada para declarar a variável:

+ +
g = 17;
+delete g;
+
+ +

Comparando Objetos

+ +

Em JavaScript, objetos são um tipo de referência. Dois objetos distintos nunca são iguais, mesmo que tenham as mesmas propriedades. Apenas comparando o mesmo objeto de referência com ele mesmo produz verdadeiro.

+ +
// Duas variáveis, dois objetos distintos com as mesmas propriedades
+var fruit = {name: "apple"};
+var fruitbear = {name: "apple"};
+
+fruit == fruitbear // return false
+fruit === fruitbear // return false
+ +
// Duas variáveis, um único objeto
+var fruit = {name: "apple"};
+var fruitbear = fruit;  // assign fruit object reference to fruitbear
+
+// Here fruit and fruitbear are pointing to same object
+fruit == fruitbear // return true
+fruit === fruitbear // return true
+ +

Para mais informações sobre comparaçāo de operadores, veja Operadores de comparaçāo.

+ +

Veja também

+ + + +
{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}
-- cgit v1.2.3-54-g00ecf