Inicializador de Objeto
=======================

Objetos podem ser inicializados utilizando `new Object()`, `Object.create()`, ou a notação *literal*. Um inicializador de objetos é uma lista de zero ou mais pares de *propriedade: valor*, separados por vírgula e fechado por um par de chaves (`{}`).

Sintaxe
-------


```js
var o = {};
var o = { a: "foo", b: 42, c: {} };

var a = "foo",
  b = 42,
  c = {};
var o = { a: a, b: b, c: c };

var o = {
  propriedade: function ([parâmetros]) {},
  get propriedade() {},
  set propriedade(valor) {},
};
```

### Novas notações em ECMAScript 2015

Por favor, verifique o suporte das anotações na tabela de compatibilidade. Em ambientes que não dão suporte às anotações, ocorrerá erros de sintaxe.


```js
// // Abreviação em nomes de propriedades (ES2015)
var a = "foo",
  b = 42,
  c = {};
var o = { a, b, c };

// // Abreviação em nomes de métodos (ES2015)
var o = {
  property([parameters]) {},
  get property() {},
  set property(value) {},
};

// Nomes de propriedades computados (ES2015)
var prop = "foo";
var o = {
  [prop]: "hey",
  ["b" + "ar"]: "there",
};
```

Descrição
---------

Um inicializador de objetos é uma expressão que descreve a inicialização de um `Object`. Objects consiste de *propriedades*, as quais descrevem um objeto. Os valores das propriedades de um objeto podem ser tipos de dados primitivos ou outros objetos .

### Criando objetos

Um objeto vazio, sem propriedades, pode ser criado como:


```js
var object = {};
```


Contudo, a vantagem em utilizar a notação *literal* ou o *inicializador* é a possibilidade de rapidamente criar objetos com propriedades dentro de chaves (`{}`). Você simplesmente cria uma lista de pares *chave: valor*, separados por vírgula. O código abaixo cria um objeto com três propriedades, sendo as chaves "foo", "age" e "baz", com seus respectivos valores, tipo string de valor "bar", tipo number de valor 42 e, por último, um outro objeto com seus respectivos pares de *chave: valor*.


```js
var object = {
  foo: "bar",
  age: 42,
  baz: { myProp: 12 },
};
```

### Acessando propriedades

Uma vez que você criou um objeto, é interessante que possa ler ou alterá-lo. As propriedades de um objeto podem ser acessadas utilizando a notação de ponto ou colchetes. Veja assessores de propriedade para mais informações.


```js
object.foo; // "bar"
object["age"]; // 42

object.foo = "baz";
```

### Definições de propriedade

Nós temos aprendido como descrever propriedades utilizando a sintaxe *inicializador*. No entanto, às vezes, há variáveis que queremos inserir em nosso objeto. Então teremos um código parecido como abaixo:


```js
var a = "foo",
  b = 42,
  c = {};

var o = {
  a: a,
  b: b,
  c: c,
};
```


Com ECMAScript 2015, há uma notação mais curta que possibilita atingir o mesmo resultado:


```js
var a = "foo",
  b = 42,
  c = {};

// Abreviação em nomes de propriedades (ES2015)
var o = { a, b, c };

// Em outras palavras,
console.log(o.a === { a }.a); // true
```


#### Duplicação em nomes de propriedades

Quando se está utilizando o mesmo nome para suas propriedades, a última sobrescreverá as anteriores.


```js
var a = { x: 1, x: 2 };
console.log(a); // { x: 2}
```


Em códigos ECMAScript 5 no modo estrito, duplicação em nomes de propriedades serão consideradas `SyntaxError` (en-US). Porém, com a introdução de "nomes de propriedades computadas", tornou-se possível a duplicação das propriedades em tempo de execução. Assim, ECMAScript 2015 removeu a restrição.


```js
function haveES2015DuplicatePropertySemantics() {
  "use strict";
  try {
    ({ prop: 1, prop: 2 });

    // No error thrown, duplicate property names allowed in strict mode
    return true;
  } catch (e) {
    // Error thrown, duplicates prohibited in strict mode
    return false;
  }
}
```

### Definição de métodos

Uma propriedade de um objeto pode se referir à function, ou aos métodos getter ou setter.


```js
var o = {
  propriedade: function ([parâmetros]) {},
  get propriedade() {},
  set propriedade(valor) {},
};
```


No ECMAScript 2015, uma notação abreviada está disponível, dispensando o uso da palavra reservada "function".


```js
// Abreviações em nomes de métodos (ES2015)
var o = {
  propriedade([parâmetros]) {},
  get propriedade() {},
  set propriedade(valor) {},
  \*gerador() {},
};
```


Com ECMAScript 2015, há uma forma concisa em criar propriedades cujo valor é uma função gerador.


```js
var o = {
  \* gerador() {
    ...........
  }
};
```


Mas em ECMAScript 5, você escreveria (lembrar que em ES5 não há geradores):


```js
var o = {
  generator: function \*() {
    ...........
  }
};
```


Para mais informações e exemplos, veja definições de método.

### Nomes de propriedades computados

Começando com ECMAScript 2015, a sintaxe *inicializador* de objeto também suporta "nomes de propriedades computados". Isso permite que você possa inserir uma expressão dentro de colchetes `[]`, que será computada como o nome de uma propriedade. Isto é semelhante à notação de chaves utilizado em acessor de propriedade, utilizado para ler a alterar as propriedades existentes em um objeto. Segue um exemplo utilizando a mesma sintaxe em objetos literais:


```js
// Nomes de propriedades computados (ES2015)
var i = 0;
var a = {
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
  ["foo" + ++i]: i,
};

console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3

var param = "size";
var config = {
  [param]: 12,
  ["mobile" + param.charAt(0).toUpperCase() + param.slice(1)]: 4,
};

console.log(config); // { size: 12, mobileSize: 4 }
```

### Mutação Prototype

Uma definição de propriedade na forma de `__proto__: valor` or `"__proto__": valor` não cria uma propriedade com o nome `__proto__`. Inclusive, se o valor fornecido for um objeto ou `null`, muda o `[[Prototype]]` do objeto criado para o valor informado. (Se o valor fornecido não é um objeto ou null, o valor não será alterado.)


```js
var obj1 = {};
assert(Object.getPrototypeOf(obj1) === Object.prototype);

var obj2 = { \_\_proto\_\_: null };
assert(Object.getPrototypeOf(obj2) === null);

var protoObj = {};
var obj3 = { \_\_proto\_\_: protoObj };
assert(Object.getPrototypeOf(obj3) === protoObj);

var obj4 = { \_\_proto\_\_: "not an object or null" };
assert(Object.getPrototypeOf(obj4) === Object.prototype);
assert(!obj4.hasOwnProperty("\_\_proto\_\_"));
```


Apenas uma única mudança em prototype é permitida em um objeto: múltiplas mudanças gera erro de sintaxe.

Definições de propriedade que não utilizam da notação de ":", não são consideradas mudanças de prototype: são definições de propriedades que se comportam de forma semelhante às definições utilizando qualquer outro nome.


```js
var __proto__ = "variable";

var obj1 = { __proto__ };
assert(Object.getPrototypeOf(obj1) === Object.prototype);
assert(obj1.hasOwnProperty("\_\_proto\_\_"));
assert(obj1.__proto__ === "variable");

var obj2 = {
  \_\_proto\_\_() {
    return "hello";
  },
};
assert(obj2.\_\_proto\_\_() === "hello");

var obj3 = { ["\_\_prot" + "o\_\_"]: 17 };
assert(obj3.__proto__ === 17);
```

Notação de objeto literal vs JSON
---------------------------------

A notação de objeto literal não é a mesma de **J**ava**S**cript **O**bject **N**otation (JSON). Mesmo que possuam semelhanças, há as seguintes diferenças:

* JSON permite definições de propriedades utilizando apenas aspas duplas, como `"propriedade": valor`. E a definição não pode ser abreviada.
* Os valores JSON podem ser apenas strings, numbers, arrays, `true`, `false`, `null`, ou outro objeto JSON.
* Uma função como valor (veja "Métodos" acima) não pode ser atribuido em JSON.
* Objetos como `Date` serão do tipo string após `JSON.parse()`.
* `JSON.parse()` rejeitará "nomes de propriedades computados" e um erro será lançado.
Especificações
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-object-initializer |

Compatibilidade com navegadores
-------------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

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

* Assesores de propriedade
* `get` / `set`
* Definições de métodos
* Lexical grammar