Sabemos que os objetos, são usados para armazenar coleções codificadas e arrays são usados para armazenar coleções ordenadas. Mas isso não é suficiente para a vida real. É por isso que aprenderemos sobre Map
e Set
.
Map
Map é uma coleção de itens de dados com chave, assim como um arquivo Object
. Mas a principal diferença, é que Map
permite chaves de qualquer tipo.
Métodos e propeidades são:
-
new Map()
- cria o map. - map.set(key, value) - armazena o valor pela chave.
- map.get(key) - retorna o valor pela chave e undefined, caso a key não exista no map.
- map.has(key) - retorna true se a key existir, false caso contrário.
- map.delete(key) - remove o elemento (o par de chave/valor) pela chave.
- map.clear() - remove tudo do map.
- map.size - retorna a contagem do elemento atual.
Por exemplo:
let map = new Map()
`map.set('1', 'str1')` // uma key string
`map.set(1, 'num1')` // uma key numérica
`map.set(true, 'bool1')` // uma key booleana
// lembra do objeto regular? converteria as chaves em string
// O map mantém o tipo, então esses dois são diferentes:
alert( map.get(1) ); // 'num1'
alert( map.get('1') ); // 'str1'
alert( map.size ); // 3
Como podemos ver, ao contrário dos objetos, as chaves não são convertidas em strings. Qualquer tipo de chave é possível.
map[key] não é a maneira certa de usar um Map
Embora map[key]
também funcione, por exemplo, podemos definir map[key] = 2
, isso é tratar o map como um objeto JavaScript simples, portanto, implica todas as limitações correspondentes (apenas chaves de strings/símbolo e assim por diante).
O map também pode usar objetos como chaves
Por exemplo:
let john = { name: "John" };
// para cada usuário, vamos armazenar a contagem de visitas
let visitsCountMap = new Map();
// john é a chave para o map
visitsCountMap.set(john, 123);
alert( visitsCountMap.get(john) ); // 123
Usar objetos como chaves, é um dos recursos mais notáveis e importantes do Map
. O mesmo não conta para Object. String como uma chave em Object
está correto, mas não podemos usar outro Object
como uma chave em Object
.
Vamos tentar:
let john = { name: "John" };
let ben = { name: "Ben" };
let visitsCountObj = {}; // tente usar um objeto
visitsCountObj[ben] = 234; // tente usar o objeto ben como a chave
visitsCountObj[john] = 123; // tente usar o objeto john como a chave, o objeto ben será substituído
// Isso é o que está retornando!
alert( visitsCountObj["[object Object]"] ); // 123
Como visitsCountObj
é um objeto, ele converte todas as chaves Object
, como john e ben acima, na mesma string "[object Object]". Definitivamente não é o que queremos.
Iteração sobre o map
Para fazer um loop sobre um map, existem 3 métodos:
-
map.keys()
- retorna um iterável para chaves, -
map.values()
- retorna um iterável para valores, -
map.entries()
- retorna um iterável para[keys, value]
, é usado por padrão emfor...of
.
Por exemplo:
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
// iterar sobre chaves (vegetais)
for (let vegetable of recipeMap.keys()) {
alert(vegetable); // cucumber, tomatoes, onion
}
// iterar sobre valores (quantidades)
for (let amount of recipeMap.values()) {
alert(amount); // 500, 350, 50
}
// iterar sobre valores [key, value]
for (let entry of recipeMap) { // o mesmo de recipeMap.entries()
alert(entry); // pepino, 500 (e assim por diante)
}
A ordem de iserção é usada
A iteração ocorre na mesma ordem em que os valores foram inseridos. Map preserva essa ordem, ao contrário de um Object
.
Além disso, Map
possui um método forEach
embutido, semelhante a um Array:
// executa a função para cada par (key, value)
recipeMap.forEach( (value, key, map) => {
alert(`${key}: ${value}`); // pepino: 500 etc
});
Object.entries: Map from Object
Quando um Map é criado, podemos passar um array (ou outro iterável) com pares chave/valor para inicialização, assim:
// array of [key, value] pairs
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, 'bool1']
]);
alert( map.get('1') ); // str1
Se tivermos um objeto simples e quisermos criar um Map a partir dele, podemos usar o método integrado Object.entries(obj)
que retorna uma array de pares de chave/valor para um objeto exatamente nesse formato.
Assim, podemos criar um map a partir de um objeto como esse:
let obj = {
name: "John",
age: 30
};
let map = new Map(Object.entries(obj));
alert( map.get('name') ); // John
Aqui, Object.entries
retorna o array de pares chave/valor: [ ["name","John"], ["age", 30] ]
. Isso é o que Mapprecisa.
Object.fromEntries: Object from Map
Acabamos de ver como criar Map a partir de um objeto simples com Object.entries(obj). Existe o método Object.fromEntries que faz o contrário: dado um array de pares [chave, valor], ele cria um objeto a partir deles:
let prices = Object.fromEntries([
['banana', 1],
['orange', 2],
['meat', 4]
]);
// now prices = { banana: 1, orange: 2, meat: 4 }
alert(prices.orange); // 2
Podemos usar Object.fromEntries
para obter um objeto simples de Map. Por exemplo, armazenamos os dados em um map, mas precisamos passá-los para um código de terceiros que espera um objeto simples. Aqui vamos nós:
let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 4);
let obj = Object.fromEntries(map.entries()); // make a plain object (*)
// done!
// obj = { banana: 1, orange: 2, meat: 4 }
alert(obj.orange); // 2
Uma chamada para map.entries()
retorna um iterável de pares chave/valor, exatamente no formato correto para Object.fromEntries. Também poderíamos tornar a linha (*) mais curta:
let obj = Object.fromEntries(map); // omit .entries()
Isso é o mesmo, porque Object.fromEntries espera um objeto iterável como argumento. Não necessariamente uma array. E a iteração padrão para map, retorna os mesmos pares chave/valor de map.entries()
. Assim, obtemos um objeto simples com os mesmos valores/chave do mapa.
Set
Uma Set
é uma coleção de tipo especial – “conjunto de valores” (sem chaves), onde cada valor pode ocorrer apenas uma vez.
Seus principais métodos são:
-
new Set([iterable])
– cria o conjunto e, se um objeto iterable for fornecido (geralmente um array), copia os valores dele para o conjunto. -
set.add(value)
– adiciona um valor, retorna o próprio conjunto. -
set.delete(value)
– remove o valor, retorna true se value existir no momento da chamada, caso contrário false. -
set.has(value)
– retorna true se o valor existir no conjunto, caso contrário false. -
set.clear()
– remove tudo do conjunto. -
set.size
– é a contagem de elementos.
A principal característica é que chamadas repetidas de set.add(value)
com o mesmo valor não fazem nada. É por isso que cada valor Set
aparece apenas uma vez.
Por exemplo, temos visitantes chegando e gostaríamos de lembrar de todos. Mas visitas repetidas não devem levar a duplicatas. Um visitante deve ser “contado” apenas uma vez. Por exemplo;
let set = new Set();
let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };
// visitas, alguns usuários vêm várias vezes
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);
// set mantém apenas valores únicos
alert( set.size ); // 3
for (let user of set) {
alert(user.name); // John (então Pete e Mary)
}
Uma alternativa a Set pode ser uma array de usuários e o código para verificar se há duplicatas em cada inserção usando arr.find
. Mas o desempenho seria muito pior, porque esse método percorre todo o array verificando cada elemento. Set é muito melhor otimizado internamente para verificações de exclusividade.
Iteração sobre Conjunto
Podemos percorrer um conjunto com for..of
ou usando forEach
:
let set = new Set(["laranjas", "maçãs", "bananas"]);
for (let value of set) alert(value);
// o mesmo com forEach:
set.forEach((value, valueAgain, set) => {
alert(value);
});
Observe uma coisa engraçada. A função de retorno de chamada de forEach
possui 3 argumentos: um value, o mesmo valor valueAgain
e, em seguida, o objeto de destino. De fato, o mesmo valor aparece nos argumentos duas vezes.
Isso é para compatibilidade com Map onde o callback passado forEach
tem três argumentos. Parece um pouco estranho, com certeza. Mas isso pode ajudar a substituir Map com Set com facilidade em certos casos e vice-versa.
Os mesmos métodos Mappara iteradores também são suportados:
-
set.keys()
– retorna um objeto iterável para valores, -
set.values()
– o mesmo que set.keys(), para compatibilidade com Map, -
set.entries()
– retorna um objeto iterável para entradas [value, value], existe para compatibilidade com Map.
Resumo
Map – é uma coleção de valores chaveados.
Métodos e propriedades:
-
new Map([iterable])
– cria o map, com opcional iterable(por exemplo, array) de pares [key,value] para inicialização. -
map.set(key, value)
– armazena o valor pela chave, retorna o próprio map. -
map.get(key)
– retorna o valor pela chave, undefined caso key não exista no map. -
map.has(key)
– retorna true se a key existir, false caso contrário. -
map.delete(key)
– remove o elemento pela chave, retorna true se key existe no momento da chamada, caso contrário false. -
map.clear()
– remove tudo do map. -map.size
– retorna a contagem do elemento atual.
As diferenças de um regular Object:
Quaisquer chaves, objetos podem ser chaves.
Métodos convenientes adicionais, uma propriedade size.
Set – é uma coleção de valores únicos.
Métodos e propriedades:
-
new Set([iterable])
– cria o conjunto, com valores opcionais iterable(por exemplo, array) para inicialização. -
set.add(value)
– adiciona um valor (não faz nada se value existir), retorna o próprio conjunto.set.delete(value)
– remove o valor, retorna true se value existir no momento da chamada, caso contrário false. -
set.has(value)
– retorna true se o valor existir no conjunto, caso contrário false. -
set.clear()
– remove tudo do conjunto. -
set.size
– é a contagem de elementos.
Top comments (0)