Map() - Estrutura de dados JavaScript
Map() é uma estrutura de dados chave-valor em JavaScript que oferece uma maneira eficiente de adicionar, editar e excluir dados. Sua maior vantagem em relação aos objetos tradicionais é que suas chaves podem ser qualquer coisa que você desejar.
Por outro lado, as chaves de objetos precisam ser strings. Se você fornecer um valor para uma chave de objeto que não é uma string, ela será convertida para uma string:
const data = {};
const user = {
name: "Sam"
};
data[user] = true;
console.log(data); // {[object Object]: true}
Como você pode ver, quando fornecemos um valor de chave que não era uma string (o objeto do usuário), ele foi convertido para uma string, razão pela qual acabamos com [object Object]. Esse é o resultado da chamada .toString() em um objeto.
Operações de Map()
Vamos começar criando um Map() e inserindo dados nele:
const orders = new Map();
orders.set("table_14", "processed");
orders.set("terrace_5", "delivered");
orders.set("terrace_10", "paid");
console.log(orders); // Map(3) {'table_14' => 'processed', 'terrace_5' => 'delivered', 'terrace_10' => 'paid'}
Portanto, podemos definir um par de chave-valor usando o .set(key, value)
método.
Você pode ler as chaves existentes com o .get(key)
método:
console.log(orders.get("terrace_5")); // "delivered"
console.log(orders.get("something_else")); // undefined (it doesn't exist)
Você também pode acessar o tamanho do map() usando a size
propriedade. Isso retorna o número de itens contidos no Map(). Além disso, você pode excluir facilmente pares de chave-valor com o .delete()
método:
console.log(orders.size); // 3
orders.delete("terrace_10");
console.log(orders.size); // 2
console.log(orders); // Map(2) {'table_14' => 'processed', 'terrace_5' => 'delivered'}
Por fim, você pode iterar facilmente sobre Mapa() com o método forEach
:
orders.forEach((value, key) => {
console.log(value, key); // Logs: "processed", "table_14" and "delivered", "terrace_5"
});
Você também pode iterar usando a for...of
:
for (const order of orders) {
console.log(order);
}
Você também pode combiná-lo com a desestruturação para obter o value
e key
:
for (const [value, key] of orders) {
console.log(value, key);
}
Em geral, a sintaxe para iteração é mais fácil do que a dos objetos. Aqui está um resumo rápido e uma comparação com objetos:
- Você pode criar um map com
new Map()
. - Você pode adicionar um par de chave-valor com o
.set()
método. - Você pode acessar um valor por sua chave usando o
.get()
método. - Você pode obter o tamanho do map com a propriedade
.size
- Você pode excluir um item com o
.delete()
método. - Você pode iterar com o método
.forEach()
ou usar afor...of
.
Por outro lado, algumas das tarefas acima são um pouco mais complicadas com objetos:
- Não há propriedade de tamanho embutida. Em vez disso, você precisa usar
Object.values(obj).length
. - Não há uma maneira interna de iterar. Você tem que usar
Object.entries(obj).forEach()
.
Mapear casos de uso
Se você aprecia os benefícios descritos acima, já pode utilizar Map() em vez de Objetos. No entanto, esse nem sempre é um caso forte para o uso de Map(), pois estamos todos acostumados a usar objetos.
O maior benefício de usar um Map() ocorre quando você deseja que as chaves sejam de outro tipo que não seja uma string. As chaves de objetos são restritas a strings, o que pode ser uma limitação em alguns casos.
Por exemplo, Mapas permitem que você use IDs numerados como chaves:
Por exemplo, o Map() permite usar IDs numerados como chaves:
const userRoles = new Map();
userRoles.set(5, "admin");
userRoles.set(1542, "viewer");
Se você usasse um objeto, os números seriam convertidos em uma string. Isso não é um problema para números pequenos, mas pode criar problemas no futuro e você precisa se lembrar de convertê-los em números.
Mas também podemos dar um passo adiante. E é aqui que brilha o benefício do Map().
A chave em um Map() também pode ser um objeto. Isso abre uma nova maneira de trabalhar com relacionamentos. Tradicionalmente relacionamos objetos por meio de IDs numerados, como fizemos acima. Mas então, sempre que quisermos procurar os detalhes do usuário com id
5, precisaremos encontrar o users
array de objetos para obter o nome do usuário.
Mas, usando o Maps, podemos armazenar todo o objeto do usuário como uma chave:
const users = [{
id: 5,
name: "Sam"
}, {
id: 1542,
name: "Charlie",
}];
const userRoles = new Map();
userRoles.set(users[0], "admin");
userRoles.set(users[1], "viewer");
A chave agora é um objeto. users[0]
refere-se a { id: 5, name: "Sam"}
e isso é usado como chave.
Isso nos permite extrair todos os detalhes do usuário ao, por exemplo, iterar no userRoles
map():
userRoles.forEach((value, key) => {
console.log(key); // {id: 5, ...} and {id: 1542, ...}
});
Então, se quisermos mostrar o nome do usuário ao acessar as funções, agora podemos fazer isso facilmente. Para melhorar a legibilidade do código, renomearemos key
e user
registraremos o nome do usuário com user.name
:
userRoles.forEach((value, user) => {
console.log(user.name); // "Sam" and "Charlie"
});
Mapa vs. Objeto
Então, qual você deve usar?
Se você quiser usar o Map() para tudo, provavelmente poderá fazer isso. Na prática, porém, todos nós usamos objetos porque estamos acostumados com eles, eles têm uma sintaxe de leitura/gravação mais curta (mas mais demorada para iterar).
Se você precisar de um caso de uso no qual o Map() se destaque, você deve usar o Map() para esse caso de uso. Geralmente, isso exige chaves mais avançadas do que strings.
Existem também outros casos de uso:
- O map() é otimizado para acesso frequente (adicionar/excluir). Isso seria útil se você tivesse estruturas de dados extremamente grandes. Se você tiver 500.000 entradas, provavelmente não notará nenhuma diferença.
- Map() tem outros métodos que podem ser úteis:
.has()
,.keys()
,.values()
,.entries()
e.clear()
.
Map no MDN
Recapitular:
- Map() é uma estrutura de dados de chave-valor em JavaScript que fornece uma maneira eficiente de adicionar, editar e excluir dados. Sua maior vantagem em relação aos objetos tradicionais é que suas chaves podem ser o que você quiser.
- Você pode criar um map com
new Map()
. - Você pode adicionar um par de chave-valor com o
.set()
método. - Você pode acessar um valor por sua chave usando o
.get()
método. - Você pode obter o tamanho do map() com a propriedade
.size
. - Você pode excluir um item com o
.delete()
método. - Você pode iterar com o método
.forEach()
ou usar afor...of
.