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)