Objetos

Os objetos são um tipo de dados discreto da mesma forma que cada primário é um tipo de dados, com uma diferença crítica: ao contrário dos primitivos, os objetos são mutáveis. Um objeto pode conter dados associados a identificadores, como uma variável, mas mantém o tipo de dados object, independente dos dados que contém.

Além dos primitivos, todos os valores JavaScript são objetos. No entanto, até mesmo literais primitivos apresentam um comportamento semelhante a objetos devido à herança do protótipo (link em inglês), é comum dizer que o JavaScript é efetivamente composto de objetos.

Um literal de objeto é um par de chaves que envolve zero ou mais pares de chave-valor chamados "propriedades", que podem conter qualquer valor JavaScript.

{
    "myProperty" : true
}

As chaves de propriedade podem ser qualquer símbolo ou string. Assim como na atribuição de um identificador a uma variável, as strings usadas como chaves de propriedade precisam ser previsíveis e descritivas:

let carAttributes = {
    "color" : "red"
};

carAttributes
> Object { color: "red" }

As chaves de propriedade exigem um literal de string única (') ou entre aspas duplas ("), não um literal de modelo:

let carAttributes = {
    `keyString` : false
};
> Uncaught SyntaxError: expected property name, got template literal

Os valores de propriedade podem ser de qualquer tipo. As propriedades de um objeto podem conter objetos com as próprias propriedades:

let myObject = {
    'key' : {
        'subkey' : true,
        'othersubkey' : false
    }
};

myObject;
> Object { key: Object { subkey: true, othersubkey: false } }

Quando o valor de uma propriedade é uma função, essa propriedade é chamada de "método".

const myObject = {
    "myProperty" : true,
    myMethod() {
        console.log( "This is a method." );
    }
}

myObject.myProperty;
> true

myObject.myMethod();
> "This is a method."

Também é possível criar um objeto usando a palavra-chave new:

let myObject = new Object();

Nos exemplos anteriores, os literais de objeto recém-criados foram atribuídos às variáveis. Isso não é obrigatório, porque, como qualquer outro tipo de dados, é possível usar um objeto sem um identificador em qualquer lugar em que um objeto seja esperado. No entanto, um literal de objeto requer parênteses em qualquer contexto em que possa ser confundido com uma instrução de bloco, já que a sintaxe das duas chaves compartilhadas ({}). A inicialização de uma variável nunca exige isso.

{ "value" : 2 }
> Uncaught SyntaxError: unexpected token: ':'

({ "value" : 2 })
> Object { value: 2 }

let valObj = { "value" : 2 };

valObj;
> Object { value: 2 }

Ao contrário dos primitivos, não há diferença significativa nos resultados da criação de um objeto usando new Object() e de um literal de objeto, porque o resultado em qualquer um dos casos será um objeto com propriedades herdadas do protótipo Object. No entanto, há uma diferença prática entre as duas sintaxes.

A palavra-chave new precisa definir um objeto vazio que será preenchido com dados posteriormente:

let myObject = new Object();

myObject.booleanValue = true;
myObject.stringValue = "My string.";

Um literal de objeto pode ser preenchido com dados quando é criado:

let myObject = {
    'booleanValue' : true,
    'stringValue' : "My string."
};

Embora tenha pouco uso prático, new Object() pode ser usado para transformar valores de dados primitivos em objetos do respectivo tipo, como aqueles retornados usando a palavra-chave new com a função do construtor. Por exemplo, o código a seguir é funcionalmente equivalente a new Number( 10 ):

let myObject = new Object( 10 );

myObject;
> Number { 10 }

Os valores null e undefined resultam em um objeto vazio, funcionalmente idêntico a invocar new Object() sem fornecer um argumento.

Transmitir um literal de objeto para new Object() como um argumento transmite o literal de objeto sem alterá-lo:

let myObject = new Object( { myValue : 10 } );

myObject;
> Object { myValue: 10 }

Assim como o uso de construtores para valores primitivos, o uso de construtores para objetos raramente tem benefícios em relação ao uso da notação literal do objeto. Mesmo ao criar objetos vazios para serem preenchidos com valores posteriormente, os desenvolvedores tendem a preferir a notação literal de objetos por uma questão de simplicidade.

Teste seu conhecimento

Que tipos de notação você pode usar para definir as propriedades de um objeto?

Notação por pontos
Notação por colchetes
Notação de ponto
Notação da linha

Qual das seguintes opções é a sintaxe correta para receber o valor de myProp?

myObj["myProp"];
myObj{"myProp"};
myObj("myProp");