O material, cuja tradução apresentamos a você, é dedicado ao estudo dos recursos de literais de objetos em JavaScript, em particular as inovações que apareceram nas versões recentes do padrão ECMAScript.
O JavaScript possui uma capacidade poderosa e conveniente de criar objetos usando literais de objetos. O padrão ES2015 (ES6) simplifica o trabalho com objetos ao criar aplicativos para navegadores modernos (exceto IE) e para a plataforma Node.js.

O básico
Criar objetos em alguns idiomas pode consumir muitos recursos, o que significa o tempo de trabalho do programador e os recursos de computação dos sistemas. Em particular, estamos falando sobre o fato de que, antes de criar objetos, você deve descrever as classes (por exemplo, usando a palavra-chave
class
). Em JavaScript, os objetos podem ser criados com muita rapidez e simplicidade, sem a necessidade de etapas preliminares. Considere um exemplo:
// ES5 var myObject = { prop1: 'hello', prop2: 'world', output: function() { console.log(this.prop1 + ' ' + this.prop2); } }; myObject.output(); // hello world
Na programação, objetos “descartáveis” são frequentemente usados. Eles armazenam configurações e outros dados, são usados como parâmetros de funções, como valores retornados por funções e em outras situações. Literais de objeto JavaScript nesses casos se mostram muito úteis e o ES6 expande seus recursos.
Inicialização de objetos a partir de variáveis
As propriedades dos objetos geralmente são criadas a partir de variáveis, atribuindo a eles os mesmos nomes que já estão atribuídos a essas variáveis. Por exemplo:
No ES6, você não precisa mais repetir nomes de variáveis:
Essa técnica pode ser útil para objetos retornados ao usar o padrão
Revealing Module , que permite criar espaços para nome para vários fragmentos de código, a fim de evitar conflitos de nome. Por exemplo:
// ES6 const lib = (() => { function sum(a, b) { return a + b; } function mult(a, b) { return a * b; } return { sum, mult }; }()); console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
Você pode ter visto como essa técnica é usada nos módulos ES6:
// lib.js function sum(a, b) { return a + b; } function mult(a, b) { return a * b; } export { sum, mult };
Sintaxe abreviada para declarar métodos de objeto
Ao declarar métodos de objeto no ES5, você deve usar a palavra-chave
function
:
// ES5 var lib = { sum: function(a, b) { return a + b; }, mult: function(a, b) { return a * b; } }; console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
Agora, no ES6, você não pode mais fazer isso. A seguinte maneira abreviada de declarar métodos é permitida aqui:
// ES6 const lib = { sum(a, b) { return a + b; }, mult(a, b) { return a * b; } }; console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
Deve-se notar que as funções de seta ES6 (
=>
) não podem ser usadas aqui, pois os métodos devem ter nomes. No entanto, as funções de seta podem ser usadas se você atribuir nomes explicitamente a métodos (como no ES5). Por exemplo:
// ES6 const lib = { sum: (a, b) => a + b, mult: (a, b) => a * b }; console.log( lib.sum(2, 3) ); // 5 console.log( lib.mult(2, 3) ); // 6
Chaves dinâmicas
No ES5, você não pode usar variáveis como nomes de chave, embora a chave cujo nome é atribuído à variável possa ser adicionada após a criação do objeto. Por exemplo:
// ES5 var key1 = 'one', obj = { two: 2, three: 3 }; obj[key1] = 1; // obj.one = 1, obj.two = 2, obj.three = 3
No ES6, as chaves podem ser atribuídas dinamicamente, colocando uma expressão de nome entre colchetes (
[]
). Por exemplo:
// ES6 const key1 = 'one', obj = { [key1]: 1, two: 2, three: 3 }; // obj.one = 1, obj.two = 2, obj.three = 3
Para criar uma chave, você pode usar qualquer expressão:
// ES6 const i = 1, obj = { ['i' + i]: i }; console.log(obj.i1); // 1
As chaves dinâmicas podem ser usadas para métodos e propriedades:
// ES6 const i = 2, obj = { ['mult' + i]: x => x * i }; console.log( obj.mult2(5) ); // 10
Outra questão é se é necessário criar propriedades e métodos com nomes gerados dinamicamente. A legibilidade do código que usa essa técnica pode ser reduzida. Talvez se você se deparar com situações nas quais os nomes dinâmicos parecem adequados, seria melhor pensar em usar funções ou classes de fábrica para criar objetos.
Reestruturação
Reestruturação é a extração de propriedades de objetos e sua atribuição a variáveis. Geralmente, durante o desenvolvimento do aplicativo, você precisa extrair o valor de uma propriedade do objeto e gravá-lo em uma variável. No ES5, você tinha que descrever isso da seguinte maneira, usando os comandos de acesso à propriedade:
// ES5 var myObject = { one: 'a', two: 'b', three: 'c' }; var one = myObject.one, // 'a' two = myObject.two, // 'b' three = myObject.three; // 'c'
O ES6 suporta a desestruturação. Você pode criar uma variável com o mesmo nome que possua a propriedade correspondente do objeto e faça o seguinte:
// ES6 const myObject = { one: 'a', two: 'b', three: 'c' }; const { one, two, three } = myObject; // one = 'a', two = 'b', three = 'c'
Variáveis que obtêm valores de propriedade do objeto podem realmente ter nomes, mas se diferirem dos nomes das propriedades, você deve usar a construção
{ propertyName: newVariable }
:
// ES6 const myObject = { one: 'a', two: 'b', three: 'c' }; const { one: first, two: second, three: third } = myObject; // first = 'a', second = 'b', third = 'c'
Objetos com uma estrutura complexa, na qual matrizes e outros objetos são incorporados, também podem ser usados em operações de atribuição destrutiva:
// ES6 const meta = { title: 'Enhanced Object Literals', pageinfo: { url: 'https://www.sitepoint.com/', description: 'How to use object literals in ES2015 (ES6).', keywords: 'javascript, object, literal' } }; const { title : doc, pageinfo: { keywords: topic } } = meta; /* doc = 'Enhanced Object Literals' topic = 'javascript, object, literal' */
No começo, tudo isso pode parecer complicado, no entanto, não é tão difícil descobrir, o principal é lembrar o seguinte:
- O lado direito da expressão é a fonte de dados - uma matriz ou objeto que armazena os dados a serem recuperados.
- O lado esquerdo da expressão é o objetivo da atribuição destrutiva - uma estrutura que descreve as variáveis às quais serão atribuídos os valores extraídos da matriz ou objeto.
Ao usar a desestruturação, você pode encontrar algumas dificuldades. Portanto, uma expressão não pode ser iniciada com uma chave, porque ela parecerá um bloco de código. Por exemplo:
{ a, b, c } = myObject;
Esse design é normalmente percebido pelo sistema ao declarar variáveis:
const = myObject;
Se as variáveis já estiverem declaradas, você deve colocar a expressão entre parênteses:
let a, b, c; ({ a, b, c } = myObject);
Como resultado, ao lidar com a desestruturação, você deve ter cuidado com o código e não misturar variáveis declaradas e não declaradas.
A reestruturação é uma técnica que pode ser útil em muitas situações.
Parâmetros de função padrão
Se uma função precisa de uma longa lista de argumentos, geralmente é mais fácil transmitir a ela um único objeto com parâmetros. Por exemplo:
prettyPrint( { title: 'Enhanced Object Literals', publisher: { name: 'SitePoint', url: 'https://www.sitepoint.com/' } } );
No ES5, era necessário analisar objetos com parâmetros para, se esses objetos não tiverem o que eles precisam, atribuir valores padrão aos parâmetros correspondentes:
// ES5, function prettyPrint(param) { param = param || {}; var pubTitle = param.title || 'No title', pubName = (param.publisher && param.publisher.name) || 'No publisher'; return pubTitle + ', ' + pubName; }
No ES6, qualquer parâmetro pode receber valores padrão:
// ES6 - function prettyPrint(param = {}) { ... }
Em seguida, você pode usar a desestruturação para extrair valores do objeto e, se necessário, para atribuir valores padrão:
// ES6 function prettyPrint( { title: pubTitle = 'No title', publisher: { name: pubName = 'No publisher' } } = {} ) { return `${pubTitle}, ${pubName}`; }
Vale a pena notar que esse código pode ser mais difícil de ler do que o tradicional, embora isso seja uma questão de preferências pessoais do programador.
Analisando objetos retornados por funções
As funções podem retornar apenas um valor, mas esse valor pode ser um objeto com centenas de propriedades ou métodos. No ES5, você primeiro precisava obter o objeto retornado e depois extrair os valores:
A reestruturação simplifica esse processo. Agora tudo isso pode ser feito sem a necessidade de salvar o objeto em uma variável separada e, em seguida, analisá-lo:
Você pode ter visto algo semelhante no Node.js. Por exemplo, se você precisar apenas dos métodos
writeFile()
readFile()
e
writeFile()
do módulo
fs
, poderá obter links para eles assim:
// ES6 Node.js const { readFile, writeFile } = require('fs'); readFile('file.txt', (err, data) => { console.log(err || data); }); writeFile('new.txt', 'new content', err => { console.log(err || 'file written'); });
Operador restante da sintaxe e extensão de parâmetros ES2018 (ES9)
= No ES2015, a sintaxe dos parâmetros restantes e o operador de extensão (ambos parecem três pontos,
…
) foram usados apenas ao trabalhar com matrizes. No ES2018, funcionalidade semelhante pode ser usada para trabalhar com objetos:
const myObject = ; const = myObject;
Uma abordagem semelhante pode ser usada para transferir certos valores para uma função:
function restParam({ a, ...x }) {
Observe que, nessas situações, você pode usar apenas uma expressão com três pontos no final da lista. Além disso, para objetos aninhados em outros objetos, isso não funciona.
O operador de extensão pode ser usado dentro de objetos:
const obj1 = , obj2 = ;
O operador de extensão pode ser usado para clonar objetos (
obj2 = { ...obj1 };
), mas aqui deve-se ter em mente que, com essa abordagem, é executada uma cópia superficial do objeto. Se as propriedades dos objetos forem outros objetos, o clone do objeto fará referência aos mesmos objetos aninhados.
A sintaxe dos parâmetros restantes e o operador de extensão ainda não são amplamente suportados. Atualmente, eles podem ser usados nos navegadores Chrome e Firefox sem esforços adicionais e no desenvolvimento para a plataforma Node.js. versão 8.6 e superior.
Sumário
Literais de objeto sempre foram um recurso útil do JavaScript. As inovações que aparecem no JavaScript desde o padrão ES2015 não trazem mudanças fundamentais, mas economizam o tempo do programador e ajudam a escrever um código mais limpo e conciso.
Caros leitores! Quais métodos de criação de objetos JS você usa com mais frequência?
